HierBEM v1.0.0
Hierarchical matrix based 3D Galerkin boundary element method (BEM) C++ library
hmatrix.h
Go to the documentation of this file.
1// Copyright (C) 2021-2025 Jihuan Tian <jihuan_tian@hotmail.com>
2//
3// This file is part of the HierBEM library.
4//
5// HierBEM is free software: you can use it, redistribute it and/or modify it
6// under the terms of the GNU Lesser General Public License as published by the
7// Free Software Foundation, either version 3 of the License, or (at your
8// option) any later version. The full text of the license can be found in the
9// file LICENSE at the top level directory of HierBEM.
10
19#ifndef HIERBEM_INCLUDE_HMATRIX_HMATRIX_H_
20#define HIERBEM_INCLUDE_HMATRIX_HMATRIX_H_
21
22#include <deal.II/base/logstream.h>
23#include <deal.II/base/numbers.h>
24#include <deal.II/base/thread_management.h>
25#include <deal.II/base/types.h>
26
27#include <deal.II/lac/full_matrix.h>
28#include <deal.II/lac/vector.h>
29
30#include <openblas-pthread/cblas.h>
31#include <tbb/tbb.h>
32
33#include <algorithm>
34#include <fstream>
35#include <iostream>
36#include <memory>
37#include <mutex>
38#include <queue>
39#include <sstream>
40#include <string>
41#include <type_traits>
42#include <utility>
43#include <vector>
44
47#include "config.h"
50#include "linear_algebra/lapack_full_matrix_ext.h"
51#include "rkmatrix.h"
52#include "sequence_partition/sequence_partition.h"
55
56HBEM_NS_OPEN
57
58using namespace dealii;
59
66{
71};
72
76DeclException1(ExcInvalidHMatrixType,
78 << "Invalid H-matrix node type: " << arg1);
79
83DeclException1(ExcInvalidHMatrixState,
85 << "Invalid H-matrix node state: " << arg1);
86
90DeclException1(ExcInvalidHMatrixProperty,
92 << "Invalid H-matrix node property: " << arg1);
93
98DeclException1(ExcInvalidHMatrixBlockType,
100 << "Invalid H-matrix node block type: " << arg1);
101
102template <int spacedim, typename Number = double>
104{
105public:
109 using size_type = std::make_unsigned<types::blas_int>::type;
110 using value_type = Number;
111 using real_type = typename numbers::NumberTraits<Number>::real_type;
112
117 {
125 Hilbert
126 };
127
132 {
133 A,
134 B,
135 C,
136 D
137 };
138
139 static void
140 set_leaf_set_traversal_method(const SpaceFillingCurveType type)
141 {
143 }
144
154 {
155 std::size_t
156 memory_consumption() const
157 {
158 return sizeof(VmultOrTvmultThreadData) +
159 (MemoryConsumption::memory_consumption(local_vmult_result) -
160 sizeof(local_vmult_result)) +
161 (MemoryConsumption::memory_consumption(local_tvmult_result) -
162 sizeof(local_tvmult_result));
163 }
164
170 std::pair<int64_t, int64_t> leaf_set_interval;
171
178 std::array<types::global_dof_index, 2> vmult_result_index_range;
179
186 std::array<types::global_dof_index, 2> tvmult_result_index_range;
187
208 std::array<types::global_dof_index, 2> local_vmult_result_index_range;
209
230 std::array<types::global_dof_index, 2> local_tvmult_result_index_range;
231
238 Vector<Number> local_vmult_result;
239
246 Vector<Number> local_tvmult_result;
247
254 std::vector<std::array<types::global_dof_index, 2>>
256
263 std::vector<std::array<types::global_dof_index, 2>>
265 };
266
270 using TaskNode = tbb::flow::continue_node<tbb::flow::continue_msg>;
271 using TaskNodePtr = std::shared_ptr<TaskNode>;
272
283 {
284 public:
286 TaskNodePtr node)
287 : diagonal_hmat_node(diag)
288 , update(node)
289 {}
290
296 std::size_t
298 {
299 return sizeof(*this);
300 }
301
302 HMatrix *diagonal_hmat_node;
303 TaskNodePtr update;
304 };
305
306 template <int spacedim1, typename Number1>
307 friend void
308 InitHMatrixWrtBlockClusterNode(
310 typename BlockClusterTree<spacedim1,
311 typename numbers::NumberTraits<Number1>::
312 real_type>::node_const_pointer_type bc_node);
313
314 template <int spacedim1, typename Number1>
315 friend void
316 InitHMatrixWrtBlockClusterNode(
318 typename BlockClusterTree<spacedim1,
319 typename numbers::NumberTraits<Number1>::
320 real_type>::node_const_pointer_type bc_node,
321 const std::vector<std::pair<HMatrix<spacedim1, Number1> *,
323
324 template <int spacedim1, typename Number1>
325 friend void
326 InitHMatrixWrtBlockClusterNode(
328 typename BlockClusterTree<spacedim1,
329 typename numbers::NumberTraits<Number1>::
330 real_type>::node_const_pointer_type bc_node,
331 const std::pair<HMatrix<spacedim1, Number1> *,
332 HMatrix<spacedim1, Number1> *> &hmat_pair);
333
334 template <int spacedim1, typename Number1>
335 friend void
336 InitAndCreateHMatrixChildrenWithoutAlloc(
338 typename BlockClusterTree<spacedim1,
339 typename numbers::NumberTraits<Number1>::
340 real_type>::node_const_pointer_type bc_node);
341
342 template <int spacedim1, typename Number1>
343 friend void
344 InitAndCreateHMatrixChildren(
346 typename BlockClusterTree<spacedim1,
347 typename numbers::NumberTraits<Number1>::
348 real_type>::node_const_pointer_type bc_node,
349 const unsigned int fixed_rank_k,
350 const HMatrixSupport::Property top_hmat_node_property);
351
352 template <int spacedim1, typename Number1>
353 friend void
354 InitAndCreateHMatrixChildren(
356 typename BlockClusterTree<spacedim1,
357 typename numbers::NumberTraits<Number1>::
358 real_type>::node_const_pointer_type bc_node,
359 const unsigned int fixed_rank_k,
361 const HMatrixSupport::Property top_hmat_node_property);
362
363 template <int spacedim1, typename Number1>
364 friend void
365 InitAndCreateHMatrixChildren(
367 typename BlockClusterTree<spacedim1,
368 typename numbers::NumberTraits<Number1>::
369 real_type>::node_const_pointer_type bc_node,
371 const HMatrixSupport::Property top_hmat_node_property);
372
373 template <int spacedim1, typename Number1>
374 friend void
375 InitAndCreateHMatrixChildren(
377 typename BlockClusterTree<spacedim1,
378 typename numbers::NumberTraits<Number1>::
379 real_type>::node_const_pointer_type bc_node,
380 const unsigned int fixed_rank_k,
382 const std::array<types::global_dof_index, 2> &M_row_index_range,
383 const std::array<types::global_dof_index, 2> &M_col_index_range,
384 const HMatrixSupport::Property top_hmat_node_property);
385
386 template <int spacedim1, typename Number1>
387 friend void
388 InitAndCreateHMatrixChildren(
390 typename BlockClusterTree<spacedim1,
391 typename numbers::NumberTraits<Number1>::
392 real_type>::node_const_pointer_type bc_node,
394 const std::array<types::global_dof_index, 2> &M_row_index_range,
395 const std::array<types::global_dof_index, 2> &M_col_index_range,
396 const HMatrixSupport::Property top_hmat_node_property);
397
398 template <int spacedim1, typename Number1>
399 friend void
400 InitAndCreateHMatrixChildren(
402 typename BlockClusterTree<spacedim1,
403 typename numbers::NumberTraits<Number1>::
404 real_type>::node_const_pointer_type bc_node,
406
407 template <int spacedim1, typename Number1>
408 friend void
409 RefineHMatrixWrtExtendedBlockClusterTree(
410 HMatrix<spacedim1, Number1> *starting_hmat,
411 HMatrix<spacedim1, Number1> *current_hmat);
412
413 template <int spacedim1, typename Number1>
414 friend void
415 convertHMatBlockToRkMatrix(HMatrix<spacedim1, Number1> *hmat_block,
416 const unsigned int fixed_rank_k,
417 const HMatrix<spacedim1, Number1> *hmat_root_block,
418 size_t *calling_counter,
419 const std::string &output_file_base_name);
420
421 // Friend functions for \hmatrix arithmetic operations.
422 template <int spacedim1, typename Number1>
423 friend void
424 h_rk_mmult(HMatrix<spacedim1, Number1> &M1,
425 const RkMatrix<Number1> &M2,
427
428 template <int spacedim1, typename Number1>
429 friend void
430 h_rk_mmult(const Number1 alpha,
432 const RkMatrix<Number1> &M2,
434
435 template <int spacedim1, typename Number1>
436 friend void
437 h_rk_mTmult(HMatrix<spacedim1, Number1> &M1,
438 const RkMatrix<Number1> &M2,
440
441 template <int spacedim1, typename Number1>
442 friend void
443 h_rk_mTmult(const Number1 alpha,
445 const RkMatrix<Number1> &M2,
447
448 template <int spacedim1, typename Number1>
449 friend void
450 h_rk_Tmmult(HMatrix<spacedim1, Number1> &M1,
451 const RkMatrix<Number1> &M2,
453
454 template <int spacedim1, typename Number1>
455 friend void
456 h_rk_Tmmult(const Number1 alpha,
458 const RkMatrix<Number1> &M2,
460
461 template <int spacedim1, typename Number1>
462 friend void
463 h_rk_mmult_for_h_h_mmult(HMatrix<spacedim1, Number1> *M1,
466 bool is_M1M2_last_in_M_Sigma_P);
467
468 template <int spacedim1, typename Number1>
469 friend void
470 rk_h_mmult(const RkMatrix<Number1> &M1,
473
474 template <int spacedim1, typename Number1>
475 friend void
476 rk_h_mmult(const Number1 alpha,
477 const RkMatrix<Number1> &M1,
480
481 template <int spacedim1, typename Number1>
482 friend void
483 rk_h_mTmult(const RkMatrix<Number1> &M1,
486
487 template <int spacedim1, typename Number1>
488 friend void
489 rk_h_mTmult(const Number1 alpha,
490 const RkMatrix<Number1> &M1,
493
494 template <int spacedim1, typename Number1>
495 friend void
496 rk_h_Tmmult(const RkMatrix<Number1> &M1,
499
500 template <int spacedim1, typename Number1>
501 friend void
502 rk_h_Tmmult(const Number1 alpha,
503 const RkMatrix<Number1> &M1,
506
507 template <int spacedim1, typename Number1>
508 friend void
509 rk_h_mmult_for_h_h_mmult(const HMatrix<spacedim1, Number1> *M1,
512 bool is_M1M2_last_in_M_Sigma_P);
513
514 template <int spacedim1, typename Number1>
515 friend void
516 h_f_mmult(HMatrix<spacedim1, Number1> &M1,
519
520 template <int spacedim1, typename Number1>
521 friend void
522 h_f_mmult(const Number1 alpha,
526
527 template <int spacedim1, typename Number1>
528 friend void
529 h_f_mTmult(HMatrix<spacedim1, Number1> &M1,
532
533 template <int spacedim1, typename Number1>
534 friend void
535 h_f_mTmult(const Number1 alpha,
539
540 template <int spacedim1, typename Number1>
541 friend void
542 h_f_Tmmult(HMatrix<spacedim1, Number1> &M1,
545
546 template <int spacedim1, typename Number1>
547 friend void
548 h_f_Tmmult(const Number1 alpha,
552
553 template <int spacedim1, typename Number1>
554 friend void
555 h_f_mmult(HMatrix<spacedim1, Number1> &M1,
558
559 template <int spacedim1, typename Number1>
560 friend void
561 h_f_mmult(const Number1 alpha,
565
566 template <int spacedim1, typename Number1>
567 friend void
568 h_f_mTmult(HMatrix<spacedim1, Number1> &M1,
571
572 template <int spacedim1, typename Number1>
573 friend void
574 h_f_mTmult(const Number1 alpha,
578
579 template <int spacedim1, typename Number1>
580 friend void
581 h_f_Tmmult(HMatrix<spacedim1, Number1> &M1,
584
585 template <int spacedim1, typename Number1>
586 friend void
587 h_f_Tmmult(const Number1 alpha,
591
592 template <int spacedim1, typename Number1>
593 friend void
594 h_f_mmult_for_h_h_mmult(HMatrix<spacedim1, Number1> *M1,
597 bool is_M1M2_last_in_M_Sigma_P);
598
599 template <int spacedim1, typename Number1>
600 friend void
601 f_h_mmult(const LAPACKFullMatrixExt<Number1> &M1,
604
605 template <int spacedim1, typename Number1>
606 friend void
607 f_h_mmult(const Number1 alpha,
611
612 template <int spacedim1, typename Number1>
613 friend void
614 f_h_mTmult(const LAPACKFullMatrixExt<Number1> &M1,
617
618 template <int spacedim1, typename Number1>
619 friend void
620 f_h_mTmult(const Number1 alpha,
624
625 template <int spacedim1, typename Number1>
626 friend void
627 f_h_Tmmult(const LAPACKFullMatrixExt<Number1> &M1,
630
631 template <int spacedim1, typename Number1>
632 friend void
633 f_h_Tmmult(const Number1 alpha,
637
638 template <int spacedim1, typename Number1>
639 friend void
640 f_h_mmult(const LAPACKFullMatrixExt<Number1> &M1,
643
644 template <int spacedim1, typename Number1>
645 friend void
646 f_h_mmult(const Number1 alpha,
650
651 template <int spacedim1, typename Number1>
652 friend void
653 f_h_mTmult(const LAPACKFullMatrixExt<Number1> &M1,
656
657 template <int spacedim1, typename Number1>
658 friend void
659 f_h_mTmult(const Number1 alpha,
663
664 template <int spacedim1, typename Number1>
665 friend void
666 f_h_Tmmult(const LAPACKFullMatrixExt<Number1> &M1,
669
670 template <int spacedim1, typename Number1>
671 friend void
672 f_h_Tmmult(const Number1 alpha,
676
677 template <int spacedim1, typename Number1>
678 friend void
679 f_h_mmult_for_h_h_mmult(const HMatrix<spacedim1, Number1> *M1,
682 bool is_M1M2_last_in_M_Sigma_P);
683
684 template <int spacedim1, typename Number1>
685 friend void
686 h_h_mmult_phase1_recursion(
688 BlockClusterTree<spacedim1,
689 typename numbers::NumberTraits<Number1>::real_type> &Tind);
690
691 template <int spacedim1, typename Number1>
692 friend void
693 h_h_mmult_phase2(
695 BlockClusterTree<spacedim1,
696 typename numbers::NumberTraits<Number1>::real_type>
697 &target_bc_tree,
698 const unsigned int fixed_rank);
699
700 template <int spacedim1, typename Number1>
701 friend void
702 h_h_mmult_from_leaf_node(
707 const HMatrixSupport::BlockType block_type_for_local_Z,
708 const unsigned int fixed_rank,
709 const bool is_result_matrix_symm_apriori);
710
711 template <int spacedim1, typename Number1>
712 friend void
713 h_h_mmult_from_leaf_node(
716 const Number1 alpha,
719 const HMatrixSupport::BlockType block_type_for_local_Z,
720 const unsigned int fixed_rank,
721 const bool is_result_matrix_store_tril_only);
722
723 template <int spacedim1, typename Number1>
724 friend void
725 h_h_mmult_from_leaf_node_for_parallel_lu(
728 const Number1 alpha,
731 const HMatrixSupport::BlockType block_type_for_local_Z,
732 const unsigned int fixed_rank,
733 const bool is_result_matrix_store_tril_only);
734
735 template <int spacedim1, typename Number1>
736 friend void
737 h_h_mTmult_from_leaf_node(
742 const HMatrixSupport::BlockType block_type_for_local_Z,
743 const unsigned int fixed_rank,
744 const bool is_result_matrix_store_tril_only);
745
746 template <int spacedim1, typename Number1>
747 friend void
748 h_h_mTmult_from_leaf_node(
751 const Number1 alpha,
754 const HMatrixSupport::BlockType block_type_for_local_Z,
755 const unsigned int fixed_rank,
756 const bool is_result_matrix_store_tril_only);
757
758 template <int spacedim1, typename Number1>
759 friend void
760 h_h_mTmult_from_leaf_node_for_parallel_cholesky(
763 const Number1 alpha,
766 const HMatrixSupport::BlockType block_type_for_local_Z,
767 const unsigned int fixed_rank,
768 const bool is_result_matrix_store_tril_only);
769
770 template <int spacedim1, typename Number1>
771 friend void
772 h_h_Tmmult_from_leaf_node(
777 const HMatrixSupport::BlockType block_type_for_local_Z,
778 const unsigned int fixed_rank,
779 const bool is_result_matrix_store_tril_only);
780
781 template <int spacedim1, typename Number1>
782 friend void
783 h_h_Tmmult_from_leaf_node(
786 const Number1 alpha,
789 const HMatrixSupport::BlockType block_type_for_local_Z,
790 const unsigned int fixed_rank,
791 const bool is_result_matrix_store_tril_only);
792
793 template <int spacedim1, typename Number1>
794 friend void
795 h_h_mmult_level_conserving(HMatrix<spacedim1, Number1> &M,
798 const unsigned int fixed_rank,
799 const bool is_result_matrix_store_tril_only);
800
801 template <int spacedim1, typename Number1>
802 friend void
803 h_h_mmult_level_conserving(HMatrix<spacedim1, Number1> &M,
804 const Number1 alpha,
807 const unsigned int fixed_rank,
808 const bool is_result_matrix_store_tril_only);
809
810 template <int spacedim1, typename Number1>
811 friend void
812 h_h_mmult_level_conserving_for_parallel_lu(
814 const Number1 alpha,
817 const unsigned int fixed_rank,
818 const bool is_result_matrix_store_tril_only);
819
820 template <int spacedim1, typename Number1>
821 friend void
822 h_h_mTmult_level_conserving(HMatrix<spacedim1, Number1> &M,
825 const unsigned int fixed_rank,
826 const bool is_result_matrix_store_tril_only);
827
828 template <int spacedim1, typename Number1>
829 friend void
830 h_h_mTmult_level_conserving(HMatrix<spacedim1, Number1> &M,
831 const Number1 alpha,
834 const unsigned int fixed_rank,
835 const bool is_result_matrix_store_tril_only);
836
837 template <int spacedim1, typename Number1>
838 friend void
839 h_h_mTmult_level_conserving_for_parallel_cholesky(
841 const Number1 alpha,
844 const unsigned int fixed_rank,
845 const bool is_result_matrix_store_tril_only);
846
847 template <int spacedim1, typename Number1>
848 friend void
849 h_h_Tmmult_level_conserving(HMatrix<spacedim1, Number1> &M,
852 const unsigned int fixed_rank,
853 const bool is_result_matrix_store_tril_only);
854
855 template <int spacedim1, typename Number1>
856 friend void
857 h_h_Tmmult_level_conserving(HMatrix<spacedim1, Number1> &M,
858 const Number1 alpha,
861 const unsigned int fixed_rank,
862 const bool is_result_matrix_store_tril_only);
863
864 template <int spacedim1, typename Number1>
865 friend void
866 copy_hmatrix_node(HMatrix<spacedim1, Number1> &hmat_dst,
867 const HMatrix<spacedim1, Number1> &hmat_src);
868
869 template <int spacedim1, typename Number1>
870 friend void
871 copy_hmatrix_node(HMatrix<spacedim1, Number1> &hmat_dst,
872 HMatrix<spacedim1, Number1> &&hmat_src);
873
874 template <int spacedim1, typename Number1>
875 friend void
876 copy_hmatrix(HMatrix<spacedim1, Number1> &hmat_dst,
877 const HMatrix<spacedim1, Number1> &hmat_src);
878
879 template <int spacedim1, typename Number1>
880 friend void
881 print_h_submatrix_accessor(std::ostream &out,
882 const std::string &name,
884
885 template <int spacedim1, typename Number1>
886 friend void
887 print_h_h_submatrix_mmult_accessor(std::ostream &out,
888 const std::string &name1,
890 const std::string &name2,
892
893 template <int spacedim1, typename Number1>
894 friend void
895 hmatrix_solve_lu(const HMatrix<spacedim1, Number1> &L,
897 Vector<Number1> &x,
898 const Vector<Number1> &b);
899
900 template <int spacedim1, typename Number1>
901 friend void
902 hmatrix_solve_cholesky(const HMatrix<spacedim1, Number1> &L,
903 Vector<Number1> &x,
904 const Vector<Number1> &b);
905
911 static const unsigned int submatrix_index_invalid = 9;
912
920
931 const unsigned int fixed_rank_k = 1,
932 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
934 HMatrixSupport::BlockType::undefined_block);
935
947 bc_node,
948 const unsigned int fixed_rank_k = 1,
949 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
951 HMatrixSupport::BlockType::undefined_block);
952
965 const unsigned int fixed_rank_k,
967 HMatrixSupport::BlockType::diagonal_block);
968
984 HMatrixSupport::BlockType::diagonal_block);
985
1001 bc_node,
1003 const unsigned int fixed_rank_k,
1004 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
1006 HMatrixSupport::BlockType::undefined_block);
1007
1025 bc_node,
1027 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
1029 HMatrixSupport::BlockType::undefined_block);
1030
1040 bc_node,
1042 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
1044 HMatrixSupport::BlockType::undefined_block);
1045
1060 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
1062 HMatrixSupport::BlockType::diagonal_block);
1063
1069
1080
1088 void
1091 const unsigned int fixed_rank_k = 1,
1092 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
1094 HMatrixSupport::BlockType::diagonal_block);
1095
1102 void
1105 bc_node,
1106 const unsigned int fixed_rank_k = 1,
1107 const HMatrixSupport::Property property = HMatrixSupport::Property::general,
1109 HMatrixSupport::BlockType::undefined_block);
1110
1119
1128
1146 template <typename MatrixType>
1147 void
1148 convertToFullMatrix(MatrixType &M) const;
1149
1153 void
1155
1159 void
1161
1165 void
1167
1171 void
1173
1178 void
1180
1185
1192 get_type() const;
1193
1199 bool
1200 is_root() const;
1201
1207 bool
1209
1215 bool
1217
1223 bool
1224 is_leaf() const;
1225
1230 size_type
1231 get_m() const;
1232
1237 unsigned int
1239
1244 unsigned int
1246
1253
1258 void
1260
1267 void
1269
1278 void
1280
1291 void
1293
1299 void
1301
1308 get_state() const;
1309
1315 void
1317
1324
1330 void
1332
1338 void
1340
1345 size_type
1346 get_n() const;
1347
1355
1361 const RkMatrix<Number> *
1363
1368 void
1370
1378
1386
1392 std::vector<HMatrix<spacedim, Number> *> &
1394
1400 const std::vector<HMatrix<spacedim, Number> *> &
1402
1414 void
1415 print_formatted(std::ostream &out,
1416 const unsigned int precision = 3,
1417 const bool scientific = true,
1418 const unsigned int width = 0,
1419 const char *zero_string = " ",
1420 const double denominator = 1.,
1421 const double threshold = 0.) const;
1422
1428 void
1429 print_matrix_info(std::ostream &out) const;
1430
1436 void
1437 print_current_matrix_info(std::ostream &out) const;
1438
1445 void
1446 print_matrix_info_as_dot(std::ostream &out);
1447
1460 void
1462 const std::string &name,
1463 const unsigned int precision = 8,
1464 const bool scientific = true,
1465 const unsigned int width = 0,
1466 const char *zero_string = "0",
1467 const double denominator = 1.,
1468 const double threshold = 0.) const;
1469
1475 void
1476 print_leaf_set_info(std::ostream &out) const;
1477
1493 void
1495 std::ostream &out,
1496 const real_type singular_value_threshold = 0.) const;
1497
1512 void
1513 write_rkmatrix_leaf_node(std::ostream &out) const;
1514
1530 void
1531 write_leaf_set(std::ostream &out,
1532 const real_type singular_value_threshold = 0.) const;
1533
1549 void
1551 std::ostream &out,
1552 const real_type singular_value_threshold = 0.) const;
1553
1565 HMatrix *
1567
1579 HMatrix *
1581
1596 void
1598
1621 void
1623 size_type new_rank,
1624 const bool is_only_handle_tril = true);
1625
1635 void
1637 size_type new_rank,
1638 const bool is_only_handle_tril = true);
1639
1649 void
1651 size_type new_rank,
1652 const bool is_compensate_diag_blocks = true);
1653
1658 void
1660
1665 void
1667 std::unique_ptr<HMatrixVmultStrategy<spacedim, Number>> strategy);
1668
1697 void
1698 vmult(Vector<Number> &y,
1699 const Vector<Number> &x,
1700 const HMatrixSupport::Property top_hmat_property) const;
1701
1731 template <typename Number2>
1732 void
1733 vmult(Vector<Number> &y,
1734 const Number2 alpha,
1735 const Vector<Number> &x,
1736 const HMatrixSupport::Property top_hmat_property) const;
1737
1751 void
1752 vmult(Vector<Number> &y,
1753 const Vector<Number> &x,
1754 const HMatrix<spacedim, Number> &starting_hmat,
1755 const HMatrixSupport::Property top_hmat_property) const;
1756
1771 template <typename Number2>
1772 void
1773 vmult(Vector<Number> &y,
1774 const Number2 alpha,
1775 const Vector<Number> &x,
1776 const HMatrix<spacedim, Number> &starting_hmat,
1777 const HMatrixSupport::Property top_hmat_property) const;
1778
1791 template <typename Number2, typename Number3>
1792 void
1793 vmult_serial_iterative(const Number2 beta,
1794 Vector<Number> &y,
1795 const Number3 alpha,
1796 const Vector<Number> &x) const;
1797
1813 template <typename Number2, typename Number3>
1814 void
1815 vmult_task_parallel(const Number2 beta,
1816 Vector<Number> &y,
1817 const Number3 alpha,
1818 const Vector<Number> &x) const;
1819
1824 void
1825 vmult(Vector<Number> &y, const Vector<Number> &x) const;
1826
1831 void
1832 vmult_add(Vector<Number> &y, const Vector<Number> &x) const;
1833
1838 template <typename Number2>
1839 void
1840 vmult(Vector<Number> &y, const Number2 alpha, const Vector<Number> &x) const;
1841
1846 template <typename Number2>
1847 void
1848 vmult_add(Vector<Number> &y,
1849 const Number2 alpha,
1850 const Vector<Number> &x) const;
1851
1872 void
1873 Tvmult(Vector<Number> &y,
1874 const Vector<Number> &x,
1875 const HMatrixSupport::Property top_hmat_property) const;
1876
1898 template <typename Number2>
1899 void
1900 Tvmult(Vector<Number> &y,
1901 const Number2 alpha,
1902 const Vector<Number> &x,
1903 const HMatrixSupport::Property top_hmat_property) const;
1904
1917 void
1918 Tvmult(Vector<Number> &y,
1919 const Vector<Number> &x,
1920 const HMatrix<spacedim, Number> &starting_hmat,
1921 const HMatrixSupport::Property top_hmat_property) const;
1922
1936 template <typename Number2>
1937 void
1938 Tvmult(Vector<Number> &y,
1939 const Number2 alpha,
1940 const Vector<Number> &x,
1941 const HMatrix<spacedim, Number> &starting_hmat,
1942 const HMatrixSupport::Property top_hmat_property) const;
1943
1956 template <typename Number2, typename Number3>
1957 void
1958 Tvmult_serial_iterative(const Number2 beta,
1959 Vector<Number> &y,
1960 const Number3 alpha,
1961 const Vector<Number> &x) const;
1962
1981 template <typename Number2, typename Number3>
1982 void
1983 Tvmult_task_parallel(const Number2 beta,
1984 Vector<Number> &y,
1985 const Number3 alpha,
1986 const Vector<Number> &x) const;
1987
1992 void
1993 Tvmult(Vector<Number> &y, const Vector<Number> &x) const;
1994
2000 void
2001 Tvmult_add(Vector<Number> &y, const Vector<Number> &x) const;
2002
2007 template <typename Number2>
2008 void
2009 Tvmult(Vector<Number> &y, const Number2 alpha, const Vector<Number> &x) const;
2010
2016 template <typename Number2>
2017 void
2018 Tvmult_add(Vector<Number> &y,
2019 const Number2 alpha,
2020 const Vector<Number> &x) const;
2021
2035 void
2036 Hvmult(Vector<Number> &y,
2037 const Vector<Number> &x,
2038 const HMatrixSupport::Property top_hmat_property) const;
2039
2054 template <typename Number2>
2055 void
2056 Hvmult(Vector<Number> &y,
2057 const Number2 alpha,
2058 const Vector<Number> &x,
2059 const HMatrixSupport::Property top_hmat_property) const;
2060
2070 template <typename Number2, typename Number3>
2071 void
2072 Hvmult_task_parallel(const Number2 beta,
2073 Vector<Number> &y,
2074 const Number3 alpha,
2075 const Vector<Number> &x) const;
2076
2091 template <typename Number2, typename Number3>
2092 void
2093 Hvmult_serial_iterative(const Number2 beta,
2094 Vector<Number> &y,
2095 const Number3 alpha,
2096 const Vector<Number> &x) const;
2097
2110 void
2111 Hvmult(Vector<Number> &y,
2112 const Vector<Number> &x,
2113 const HMatrix<spacedim, Number> &starting_hmat,
2114 const HMatrixSupport::Property top_hmat_property) const;
2115
2129 template <typename Number2>
2130 void
2131 Hvmult(Vector<Number> &y,
2132 const Number2 alpha,
2133 const Vector<Number> &x,
2134 const HMatrix<spacedim, Number> &starting_hmat,
2135 const HMatrixSupport::Property top_hmat_property) const;
2136
2141 void
2142 Hvmult(Vector<Number> &y, const Vector<Number> &x) const;
2143
2149 void
2150 Hvmult_add(Vector<Number> &y, const Vector<Number> &x) const;
2151
2156 template <typename Number2>
2157 void
2158 Hvmult(Vector<Number> &y, const Number2 alpha, const Vector<Number> &x) const;
2159
2165 template <typename Number2>
2166 void
2167 Hvmult_add(Vector<Number> &y,
2168 const Number2 alpha,
2169 const Vector<Number> &x) const;
2170
2175 void
2177
2182 void
2184
2189 void
2191
2196 void
2198
2208 void
2214 const unsigned int fixed_rank = 1);
2215
2228 void
2234 const unsigned int fixed_rank,
2235 const bool adding);
2236
2246 void
2249 const unsigned int fixed_rank,
2250 const bool is_result_matrix_store_tril_only = false);
2251
2263 void
2265 const Number alpha,
2267 const unsigned int fixed_rank,
2268 const bool is_result_matrix_store_tril_only = false);
2269
2270 void
2271 mmult_level_conserving_for_parallel_lu(
2273 const Number alpha,
2275 const unsigned int fixed_rank,
2276 const bool is_result_matrix_store_tril_only = false);
2277
2288 void
2291 const unsigned int fixed_rank,
2292 const bool is_result_matrix_store_tril_only = false);
2293
2305 void
2307 const Number alpha,
2309 const unsigned int fixed_rank,
2310 const bool is_result_matrix_store_tril_only = false);
2311
2312 void
2313 mTmult_level_conserving_for_parallel_cholesky(
2315 const Number alpha,
2317 const unsigned int fixed_rank,
2318 const bool is_result_matrix_store_tril_only = false);
2319
2330 void
2333 const unsigned int fixed_rank,
2334 const bool is_result_matrix_store_tril_only = false);
2335
2347 void
2349 const Number alpha,
2351 const unsigned int fixed_rank,
2352 const bool is_result_matrix_store_tril_only = false);
2353
2374 void
2377 const size_type fixed_rank_k) const;
2378
2386 void
2388 const Number b,
2390 const size_type fixed_rank_k) const;
2391
2408 void
2409 add(const HMatrix<spacedim, Number> &B, const size_type fixed_rank_k) const;
2410
2416 void
2417 add(const Number b,
2419 const size_type fixed_rank_k) const;
2420
2432 void
2434 const std::array<types::global_dof_index, 2> &B_row_index_range,
2435 const std::array<types::global_dof_index, 2> &B_col_index_range,
2436 const size_type fixed_rank_k,
2437 const bool is_result_matrix_store_tril_only = false) const;
2438
2439 void
2441 const RkMatrix<Number> &B,
2442 const std::array<types::global_dof_index, 2> &B_row_index_range,
2443 const std::array<types::global_dof_index, 2> &B_col_index_range,
2444 const size_type fixed_rank_k,
2445 const bool is_result_matrix_store_tril_only = false);
2446
2459 void
2460 add(const Number b,
2461 const RkMatrix<Number> &B,
2462 const std::array<types::global_dof_index, 2> &B_row_index_range,
2463 const std::array<types::global_dof_index, 2> &B_col_index_range,
2464 const size_type fixed_rank_k,
2465 const bool is_result_matrix_store_tril_only = false) const;
2466
2486 void
2488 const size_type fixed_rank_k,
2489 const bool is_result_matrix_store_tril_only = false);
2490
2491 void
2493 const RkMatrix<Number> &B,
2494 const size_type fixed_rank_k,
2495 const bool is_result_matrix_store_tril_only = false);
2496
2510 void
2511 add(const Number b,
2512 const RkMatrix<Number> &B,
2513 const size_type fixed_rank_k,
2514 const bool is_result_matrix_store_tril_only = false);
2515
2522 void
2524
2531 void
2533 const RkMatrix<Number> &B,
2534 const size_type fixed_rank_k);
2535
2543 void
2545 const Number b,
2546 const RkMatrix<Number> &B,
2547 const size_type fixed_rank_k);
2548
2560 void
2562 const size_type fixed_rank_k);
2563
2576 void
2578 const bool is_unit_diagonal = true) const;
2579
2590 void
2592 const Vector<Number> &b,
2593 const bool is_unit_diagonal = true) const;
2594
2610 void
2612 const HMatrix<spacedim, Number> &starting_hmat,
2613 const bool is_unit_diagonal = true) const;
2614
2626 void
2628 const Vector<Number> &b,
2629 const HMatrix<spacedim, Number> &starting_hmat,
2630 const bool is_unit_diagonal = true) const;
2631
2652 void
2656 const unsigned int fixed_rank,
2657 const bool is_unit_diagonal = true) const;
2658
2671 void
2674 const unsigned int fixed_rank,
2675 const bool is_unit_diagonal = true) const;
2676
2694 void
2698 const unsigned int fixed_rank) const;
2699
2700 void
2703 const unsigned int fixed_rank) const;
2704
2718 void
2720
2731 void
2733 const Vector<Number> &b) const;
2734
2748 void
2750 Vector<Number> &b,
2751 const HMatrix<spacedim, Number> &starting_hmat) const;
2752
2764 void
2766 Vector<Number> &x,
2767 const Vector<Number> &b,
2768 const HMatrix<spacedim, Number> &starting_hmat) const;
2769
2785 void
2789 const unsigned int fixed_rank) const;
2790
2802 void
2805 const unsigned int fixed_rank) const;
2806
2826 void
2830 const unsigned int fixed_rank) const;
2831
2832 void
2835 const unsigned int fixed_rank) const;
2836
2865 void
2867 Vector<Number> &b,
2868 const bool is_unit_block_diagonal = true) const;
2869
2881 void
2883 Vector<Number> &x,
2884 const Vector<Number> &b,
2885 const bool is_unit_block_diagonal = true) const;
2886
2917 void
2919 Vector<Number> &b,
2920 const HMatrix<spacedim, Number> &starting_hmat,
2921 const bool is_unit_block_diagonal = true) const;
2922
2953 void
2955 Vector<Number> &x,
2956 const Vector<Number> &b,
2957 const HMatrix<spacedim, Number> &starting_hmat,
2958 const bool is_unit_block_diagonal = true) const;
2959
2975 void
2977
2995 void
2997 const Vector<Number> &b) const;
2998
3010 void
3012 Vector<Number> &b,
3013 const HMatrix<spacedim, Number> &starting_hmat) const;
3014
3026 void
3028 Vector<Number> &x,
3029 const Vector<Number> &b,
3030 const HMatrix<spacedim, Number> &starting_hmat) const;
3031
3050 void
3052 const bool is_unit_diagonal = false) const;
3053
3070 void
3072 const Vector<Number> &b,
3073 const bool is_unit_diagonal = false) const;
3074
3094 void
3096 const HMatrix<spacedim, Number> &starting_hmat,
3097 const bool is_unit_diagonal = false) const;
3098
3116 void
3118 const Vector<Number> &b,
3119 const HMatrix<spacedim, Number> &starting_hmat,
3120 const bool is_unit_diagonal = false) const;
3121
3150 void
3152 Vector<Number> &b,
3153 const bool is_unit_block_diagonal = false) const;
3154
3184 void
3186 Vector<Number> &x,
3187 const Vector<Number> &b,
3188 const bool is_unit_block_diagonal = false) const;
3189
3219 void
3221 Vector<Number> &b,
3222 const HMatrix<spacedim, Number> &starting_hmat,
3223 const bool is_unit_block_diagonal = false) const;
3224
3255 void
3257 Vector<Number> &x,
3258 const Vector<Number> &b,
3259 const HMatrix<spacedim, Number> &starting_hmat,
3260 const bool is_unit_block_diagonal = false) const;
3261
3274 void
3276
3286 void
3288 const Vector<Number> &b) const;
3289
3302 void
3304 Vector<Number> &b,
3305 const HMatrix<spacedim, Number> &starting_hmat) const;
3306
3317 void
3319 Vector<Number> &x,
3320 const Vector<Number> &b,
3321 const HMatrix<spacedim, Number> &starting_hmat) const;
3322
3335 void
3337 const unsigned int fixed_rank);
3338
3345 void
3346 compute_lu_factorization(const unsigned int fixed_rank);
3347
3355 void
3356 compute_lu_factorization_task_parallel(const unsigned int fixed_rank);
3357
3358
3374 void
3376 const unsigned int fixed_rank);
3377
3389 void
3390 compute_cholesky_factorization(const unsigned int fixed_rank);
3391
3399 void
3400 compute_cholesky_factorization_task_parallel(const unsigned int fixed_rank);
3401
3414 void
3415 solve_lu(Vector<Number> &x, const Vector<Number> &b) const;
3416
3426 void
3427 solve_cholesky(Vector<Number> &x, const Vector<Number> &b) const;
3428
3448 void
3450 const unsigned int fixed_rank_k);
3451
3469 void
3471 const std::vector<
3473 &partition,
3474 const unsigned int fixed_rank_k);
3475
3480 void
3482
3491 void
3493 const HMatrixSupport::Property top_hmat_property);
3494
3502
3510
3514 void
3516
3522 std::vector<HMatrix<spacedim, Number> *> &
3524
3530 const std::vector<HMatrix<spacedim, Number> *> &
3532
3533 std::vector<HMatrix<spacedim, Number> *> &
3534 get_near_field_leaf_set();
3535
3536 const std::vector<HMatrix<spacedim, Number> *> &
3537 get_near_field_leaf_set() const;
3538
3539 std::vector<HMatrix<spacedim, Number> *> &
3540 get_far_field_leaf_set();
3541
3542 const std::vector<HMatrix<spacedim, Number> *> &
3543 get_far_field_leaf_set() const;
3544
3552 std::array<types::global_dof_index, 2> *
3554
3562 const std::array<types::global_dof_index, 2> *
3564
3572 std::array<types::global_dof_index, 2> *
3574
3582 const std::array<types::global_dof_index, 2> *
3584
3593 typename std::vector<HMatrix<spacedim, Number> *>::iterator
3595 const BlockCluster<spacedim, real_type> &block_cluster);
3596
3605 typename std::vector<HMatrix<spacedim, Number> *>::const_iterator
3607 const BlockCluster<spacedim, real_type> &block_cluster) const;
3608
3620 void
3622
3659 void
3663 const unsigned int fixed_rank_k2 = 1);
3664
3670 void
3672 const HMatrix<spacedim, Number> *M2);
3673
3679 void
3681 const std::pair<const HMatrix<spacedim, Number> *,
3682 const HMatrix<spacedim, Number> *> &hmat_pair);
3683
3692
3699 std::size_t
3701
3708 std::size_t
3710
3715 std::size_t
3717
3722 std::size_t
3724
3729 std::size_t
3731
3741 void
3743 std::vector<double> &task_costs) const;
3744
3753 void
3755 std::vector<double> &task_costs) const;
3756
3765 void
3767 std::vector<double> &task_costs) const;
3768
3775 unsigned int
3777 const bool is_tvmult) const;
3778
3803 void
3804 prepare_for_vmult_or_tvmult(const bool is_vmult, const bool is_tvmult);
3805
3806private:
3813 void
3815
3822 void
3823 _print_matrix_info_as_dot_node(std::ostream &out) const;
3824
3831 void
3833
3838 template <typename MatrixType>
3839 void
3841 const HMatrixSupport::Property top_hmat_property =
3842 HMatrixSupport::Property::general) const;
3843
3859 bool
3861 const HMatrixSupport::Property top_hmat_property =
3862 HMatrixSupport::Property::general) const;
3863
3869 void
3871 std::vector<HMatrix *> &total_leaf_set,
3872 std::vector<HMatrix *> &total_near_field_leaf_set,
3873 std::vector<HMatrix *> &total_far_field_leaf_set,
3874 const HMatrixSupport::Property top_hmat_property) const;
3875
3876 void
3878 std::vector<HMatrix *> &total_leaf_set,
3879 std::vector<HMatrix *> &total_near_field_leaf_set,
3880 std::vector<HMatrix *> &total_far_field_leaf_set,
3881 HilbertBlockType current_hilbert_block_type,
3882 const HMatrixSupport::Property top_hmat_property) const;
3883
3884 void
3886 const unsigned int fixed_rank = 0);
3887
3888 void
3889 distribute_sigma_r_and_f_to_leaves(const unsigned int fixed_rank = 0);
3890
3891 void
3893 const unsigned int fixed_rank = 0);
3894
3905 void
3907 const size_type fixed_rank_k);
3908
3919 void
3921 const unsigned int fixed_rank) const;
3922
3933 void
3934 _compute_lu_factorization(const unsigned int fixed_rank);
3935
3941 void
3942 compute_lu_dag(tbb::flow::graph &dag,
3943 const unsigned int fixed_rank,
3944 std::mutex &log_stream_lock);
3945
3951 void
3953 std::mutex &log_stream_lock);
3954
3962 void
3963 lu_solve_upper_task(tbb::flow::graph &dag,
3965 const unsigned int fixed_rank,
3966 std::mutex &log_stream_lock);
3967
3975 void
3976 lu_solve_lower_task(tbb::flow::graph &dag,
3978 const unsigned int fixed_rank,
3979 std::mutex &log_stream_lock);
3980
3991 void
3992 lu_update_task(tbb::flow::graph &dag,
3993 HMatrix<spacedim, Number> &diag_block,
3994 HMatrix<spacedim, Number> &diag_column_block,
3995 HMatrix<spacedim, Number> &diag_row_block,
3996 const unsigned int fixed_rank,
3997 std::mutex &log_stream_lock);
3998
4002 void
4004 HMatrix<spacedim, Number> &update_block);
4005
4009 void
4011 HMatrix<spacedim, Number> &update_block);
4012
4018 void
4020 HMatrix<spacedim, Number> &factorize_block);
4021
4027 void
4029 HMatrix<spacedim, Number> &solve_upper_or_lower_block);
4030
4045 void
4047
4058 void
4060 const unsigned int fixed_rank) const;
4061
4070 void
4071 _compute_cholesky_factorization(const unsigned int fixed_rank);
4072
4078 void
4079 compute_cholesky_dag(tbb::flow::graph &dag,
4080 const unsigned int fixed_rank,
4081 std::mutex &log_stream_lock);
4082
4088 void
4090 std::mutex &log_stream_lock);
4091
4099 void
4100 cholesky_solve_upper_task(tbb::flow::graph &dag,
4102 const unsigned int fixed_rank,
4103 std::mutex &log_stream_lock);
4104
4115 void
4116 cholesky_update_task(tbb::flow::graph &dag,
4117 HMatrix<spacedim, Number> &diag_block,
4118 HMatrix<spacedim, Number> &diag_column_block1,
4119 HMatrix<spacedim, Number> &diag_column_block2,
4120 const unsigned int fixed_rank,
4121 std::mutex &log_stream_lock);
4122
4128 void
4130 HMatrix<spacedim, Number> &factorize_block);
4131
4137 void
4139 HMatrix<spacedim, Number> &solve_upper_block);
4140
4154 void
4156
4165 double
4167 const HMatrixSupport::Property top_hmat_property) const;
4168
4177 double
4179 const HMatrixSupport::Property top_hmat_property) const;
4180
4189 double
4191 const HMatrixSupport::Property top_hmat_property) const;
4192
4200 double
4202 const HMatrixSupport::Property top_hmat_property) const;
4203
4210 void
4212 const std::pair<int64_t, int64_t> &interval,
4213 const unsigned int thread_no);
4214
4221 void
4223 const std::pair<int64_t, int64_t> &interval,
4224 const unsigned int thread_no);
4225
4230 void
4232 const unsigned int thread_no);
4233
4238 void
4240 const unsigned int thread_no);
4241
4247
4253
4258
4264
4270
4274 std::unique_ptr<HMatrixVmultStrategy<spacedim, Number>> vmult_strategy;
4275
4280
4284 std::vector<HMatrix<spacedim, Number> *> submatrices;
4285
4290
4295
4301
4307
4313
4319
4323 unsigned int submatrix_index;
4324
4328 std::vector<HMatrix<spacedim, Number> *> leaf_set;
4329
4333 std::vector<HMatrix<spacedim, Number> *> near_field_leaf_set;
4334
4338 std::vector<HMatrix<spacedim, Number> *> far_field_leaf_set;
4339
4345
4351
4356
4361 std::array<types::global_dof_index, 2> *row_index_range;
4362
4367 std::array<types::global_dof_index, 2> *col_index_range;
4368
4373
4378
4384
4389 std::vector<
4390 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>>
4392
4397 std::vector<RkMatrix<Number> *> Sigma_R;
4398
4403 std::vector<LAPACKFullMatrixExt<Number> *> Sigma_F;
4404
4410
4415
4419 std::vector<UpdateTaskNodeForLUOrCholesky> update_lu_or_cholesky_graph_nodes;
4420
4425 std::mutex update_lock;
4426
4435 std::unique_ptr<std::vector<VmultOrTvmultThreadData>>
4437};
4438
4439// Initialization of the static member of \hmatrix to Z curve.
4440template <int spacedim, typename Number>
4444
4453template <int spacedim, typename Number = double>
4454void
4457 typename BlockClusterTree<spacedim,
4458 typename numbers::NumberTraits<Number>::real_type>::
4459 node_const_pointer_type bc_node)
4460{
4464 hmat.bc_node = const_cast<typename BlockClusterTree<
4465 spacedim,
4466 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
4467 bc_node);
4468
4473 hmat.row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4474 &(hmat.bc_node->get_data_reference()
4475 .get_tau_node()
4476 ->get_data_reference()
4477 .get_index_range()));
4478 hmat.col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4479 &(hmat.bc_node->get_data_reference()
4480 .get_sigma_node()
4481 ->get_data_reference()
4482 .get_index_range()));
4483
4487 hmat.m = (*hmat.row_index_range)[1] - (*hmat.row_index_range)[0];
4488 hmat.n = (*hmat.col_index_range)[1] - (*hmat.col_index_range)[0];
4489
4490 hmat.Sigma_P.clear();
4491 hmat.Sigma_R.clear();
4492 hmat.Sigma_F.clear();
4493}
4494
4495
4505template <int spacedim, typename Number = double>
4506void
4509 typename BlockClusterTree<spacedim,
4510 typename numbers::NumberTraits<Number>::real_type>::
4511 node_const_pointer_type bc_node,
4512 const std::vector<std::pair<HMatrix<spacedim, Number> *,
4513 HMatrix<spacedim, Number> *>> &Sigma_P)
4514{
4518 hmat.bc_node = const_cast<typename BlockClusterTree<
4519 spacedim,
4520 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
4521 bc_node);
4522
4527 hmat.row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4528 &(hmat.bc_node->get_data_reference()
4529 .get_tau_node()
4530 ->get_data_reference()
4531 .get_index_range()));
4532 hmat.col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4533 &(hmat.bc_node->get_data_reference()
4534 .get_sigma_node()
4535 ->get_data_reference()
4536 .get_index_range()));
4537
4541 hmat.m = (*hmat.row_index_range)[1] - (*hmat.row_index_range)[0];
4542 hmat.n = (*hmat.col_index_range)[1] - (*hmat.col_index_range)[0];
4543
4545 &hmat_pair : Sigma_P)
4546 {
4547 hmat.Sigma_P.push_back(hmat_pair);
4548 }
4549
4550 hmat.Sigma_R.clear();
4551 hmat.Sigma_F.clear();
4552}
4553
4554
4564template <int spacedim, typename Number = double>
4565void
4568 typename BlockClusterTree<spacedim,
4569 typename numbers::NumberTraits<Number>::real_type>::
4570 node_const_pointer_type bc_node,
4572 &hmat_pair)
4573{
4577 hmat.bc_node = const_cast<typename BlockClusterTree<
4578 spacedim,
4579 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
4580 bc_node);
4581
4586 hmat.row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4587 &(hmat.bc_node->get_data_reference()
4588 .get_tau_node()
4589 ->get_data_reference()
4590 .get_index_range()));
4591 hmat.col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4592 &(hmat.bc_node->get_data_reference()
4593 .get_sigma_node()
4594 ->get_data_reference()
4595 .get_index_range()));
4596
4600 hmat.m = (*hmat.row_index_range)[1] - (*hmat.row_index_range)[0];
4601 hmat.n = (*hmat.col_index_range)[1] - (*hmat.col_index_range)[0];
4602
4603 hmat.Sigma_P.push_back(hmat_pair);
4604 hmat.Sigma_R.clear();
4605 hmat.Sigma_F.clear();
4606}
4607
4608
4619template <int spacedim, typename Number = double>
4620void
4623 typename BlockClusterTree<spacedim,
4624 typename numbers::NumberTraits<Number>::real_type>::
4625 node_const_pointer_type bc_node)
4626{
4630 hmat->bc_node = const_cast<typename BlockClusterTree<
4631 spacedim,
4632 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
4633 bc_node);
4634
4639 hmat->row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4640 &(hmat->bc_node->get_data_reference()
4641 .get_tau_node()
4642 ->get_data_reference()
4643 .get_index_range()));
4644 hmat->col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4645 &(hmat->bc_node->get_data_reference()
4646 .get_sigma_node()
4647 ->get_data_reference()
4648 .get_index_range()));
4649
4653 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
4654 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
4655
4656 const unsigned int bc_node_child_num = bc_node->get_child_num();
4657 if (bc_node_child_num > 0)
4658 {
4664
4668 for (unsigned int i = 0; i < bc_node_child_num; i++)
4669 {
4673 HMatrix<spacedim, Number> *child_hmat =
4675
4680 child_hmat->state = hmat->state;
4681
4686 switch (hmat->block_type)
4687 {
4688 case HMatrixSupport::BlockType::undefined_block: {
4693 child_hmat->block_type = hmat->block_type;
4694
4695 break;
4696 }
4697 case HMatrixSupport::BlockType::diagonal_block: {
4704 switch (i)
4705 {
4706 case 0: {
4707 child_hmat->block_type =
4708 HMatrixSupport::BlockType::diagonal_block;
4709
4710 break;
4711 }
4712 case 1: {
4713 child_hmat->block_type =
4714 HMatrixSupport::BlockType::upper_triangular_block;
4715
4716 break;
4717 }
4718 case 2: {
4719 child_hmat->block_type =
4720 HMatrixSupport::BlockType::lower_triangular_block;
4721
4722 break;
4723 }
4724 case 3: {
4725 child_hmat->block_type =
4726 HMatrixSupport::BlockType::diagonal_block;
4727
4728 break;
4729 }
4730 default: {
4731 Assert(false, ExcNotImplemented());
4732 break;
4733 }
4734 }
4735
4736 break;
4737 }
4738 case HMatrixSupport::BlockType::upper_triangular_block: {
4743 child_hmat->block_type = hmat->block_type;
4744
4745 break;
4746 }
4747 case HMatrixSupport::BlockType::lower_triangular_block: {
4752 child_hmat->block_type = hmat->block_type;
4753
4754 break;
4755 }
4756 default: {
4757 Assert(false,
4758 ExcMessage(
4759 std::string("Invalid H-matrix block type: ") +
4760 std::to_string(hmat->block_type)));
4761 break;
4762 }
4763 }
4764
4769 switch (hmat->property)
4770 {
4771 case HMatrixSupport::Property::general: {
4776 child_hmat->property = HMatrixSupport::Property::general;
4777
4778 break;
4779 }
4780 case HMatrixSupport::Property::symmetric: {
4786 if (child_hmat->block_type ==
4787 HMatrixSupport::BlockType::diagonal_block)
4788 {
4789 child_hmat->property =
4790 HMatrixSupport::Property::symmetric;
4791 }
4792 else
4793 {
4794 child_hmat->property = HMatrixSupport::Property::general;
4795 }
4796
4797 break;
4798 }
4799 case HMatrixSupport::Property::hermite_symmetric: {
4805 if (child_hmat->block_type ==
4806 HMatrixSupport::BlockType::diagonal_block)
4807 {
4808 child_hmat->property =
4809 HMatrixSupport::Property::hermite_symmetric;
4810 }
4811 else
4812 {
4813 child_hmat->property = HMatrixSupport::Property::general;
4814 }
4815
4816 break;
4817 }
4818 case HMatrixSupport::Property::upper_triangular: {
4825 if (child_hmat->block_type ==
4826 HMatrixSupport::BlockType::diagonal_block)
4827 {
4828 child_hmat->property =
4829 HMatrixSupport::Property::upper_triangular;
4830 }
4831 else
4832 {
4833 child_hmat->property = HMatrixSupport::Property::general;
4834 }
4835
4836 break;
4837 }
4838 case HMatrixSupport::Property::lower_triangular: {
4845 if (child_hmat->block_type ==
4846 HMatrixSupport::BlockType::diagonal_block)
4847 {
4848 child_hmat->property =
4849 HMatrixSupport::Property::lower_triangular;
4850 }
4851 else
4852 {
4853 child_hmat->property = HMatrixSupport::Property::general;
4854 }
4855
4856 break;
4857 }
4858 default: {
4859 Assert(false,
4860 ExcMessage("Invalid H-matrix property: " +
4861 std::to_string(hmat->property)));
4862 break;
4863 }
4864 }
4865
4867 child_hmat, bc_node->get_child_pointer(i));
4868
4872 hmat->submatrices.push_back(child_hmat);
4873
4878 child_hmat->parent = hmat;
4879
4880 child_hmat->submatrix_index = i;
4881 }
4882 }
4883 else
4884 {
4894 if (bc_node->get_data_reference().get_is_near_field())
4895 {
4896 hmat->type = FullMatrixType;
4898
4907 if (hmat->block_type == HMatrixSupport::BlockType::diagonal_block)
4908 {
4909 switch (hmat->property)
4910 {
4911 case HMatrixSupport::Property::general: {
4912 hmat->fullmatrix->set_property(
4913 LAPACKSupport::Property::general);
4914
4915 break;
4916 }
4917 case HMatrixSupport::Property::symmetric: {
4918 hmat->fullmatrix->set_property(
4919 LAPACKSupport::Property::symmetric);
4920
4921 break;
4922 }
4923 case HMatrixSupport::Property::hermite_symmetric: {
4924 hmat->fullmatrix->set_property(
4925 LAPACKSupport::Property::hermite_symmetric);
4926
4927 break;
4928 }
4929 case HMatrixSupport::Property::upper_triangular: {
4930 hmat->fullmatrix->set_property(
4931 LAPACKSupport::Property::upper_triangular);
4932
4933 break;
4934 }
4935 case HMatrixSupport::Property::lower_triangular: {
4936 hmat->fullmatrix->set_property(
4937 LAPACKSupport::Property::lower_triangular);
4938
4939 break;
4940 }
4941 default: {
4942 Assert(false,
4943 ExcMessage("Invalid H-matrix property: " +
4944 std::to_string(hmat->property)));
4945 break;
4946 }
4947 }
4948 }
4949 }
4950 else
4951 {
4952 hmat->type = RkMatrixType;
4953 hmat->rkmatrix = new RkMatrix<Number>();
4954 }
4955 }
4956}
4957
4958
4974template <int spacedim, typename Number = double>
4975void
4978 typename BlockClusterTree<spacedim,
4979 typename numbers::NumberTraits<Number>::real_type>::
4980 node_const_pointer_type bc_node,
4981 const unsigned int fixed_rank_k,
4982 const HMatrixSupport::Property top_hmat_node_property =
4983 HMatrixSupport::Property::general)
4984{
4988 hmat->bc_node = const_cast<typename BlockClusterTree<
4989 spacedim,
4990 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
4991 bc_node);
4992
4997 hmat->row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
4998 &(hmat->bc_node->get_data_reference()
4999 .get_tau_node()
5000 ->get_data_reference()
5001 .get_index_range()));
5002 hmat->col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
5003 &(hmat->bc_node->get_data_reference()
5004 .get_sigma_node()
5005 ->get_data_reference()
5006 .get_index_range()));
5007
5011 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
5012 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
5013
5014 const unsigned int bc_node_child_num = bc_node->get_child_num();
5015 if (bc_node_child_num > 0)
5016 {
5022
5026 for (unsigned int i = 0; i < bc_node_child_num; i++)
5027 {
5031 HMatrix<spacedim, Number> *child_hmat =
5033
5038 child_hmat->state = hmat->state;
5039
5044 switch (hmat->block_type)
5045 {
5046 case HMatrixSupport::BlockType::undefined_block: {
5051 child_hmat->block_type = hmat->block_type;
5052
5053 break;
5054 }
5055 case HMatrixSupport::BlockType::diagonal_block: {
5062 switch (i)
5063 {
5064 case 0: {
5065 child_hmat->block_type =
5066 HMatrixSupport::BlockType::diagonal_block;
5067
5068 break;
5069 }
5070 case 1: {
5071 child_hmat->block_type =
5072 HMatrixSupport::BlockType::upper_triangular_block;
5073
5074 break;
5075 }
5076 case 2: {
5077 child_hmat->block_type =
5078 HMatrixSupport::BlockType::lower_triangular_block;
5079
5080 break;
5081 }
5082 case 3: {
5083 child_hmat->block_type =
5084 HMatrixSupport::BlockType::diagonal_block;
5085
5086 break;
5087 }
5088 default: {
5089 Assert(false, ExcNotImplemented());
5090 break;
5091 }
5092 }
5093
5094 break;
5095 }
5096 case HMatrixSupport::BlockType::upper_triangular_block: {
5101 child_hmat->block_type = hmat->block_type;
5102
5103 break;
5104 }
5105 case HMatrixSupport::BlockType::lower_triangular_block: {
5110 child_hmat->block_type = hmat->block_type;
5111
5112 break;
5113 }
5114 default: {
5115 Assert(false,
5116 ExcMessage("Invalid H-matrix block type: " +
5117 std::to_string(hmat->block_type)));
5118 break;
5119 }
5120 }
5121
5126 switch (hmat->property)
5127 {
5128 case HMatrixSupport::Property::general: {
5133 child_hmat->property = HMatrixSupport::Property::general;
5134
5135 break;
5136 }
5137 case HMatrixSupport::Property::symmetric: {
5143 if (child_hmat->block_type ==
5144 HMatrixSupport::BlockType::diagonal_block)
5145 {
5146 child_hmat->property =
5147 HMatrixSupport::Property::symmetric;
5148 }
5149 else
5150 {
5151 child_hmat->property = HMatrixSupport::Property::general;
5152 }
5153
5154 break;
5155 }
5156 case HMatrixSupport::Property::hermite_symmetric: {
5162 if (child_hmat->block_type ==
5163 HMatrixSupport::BlockType::diagonal_block)
5164 {
5165 child_hmat->property =
5166 HMatrixSupport::Property::hermite_symmetric;
5167 }
5168 else
5169 {
5170 child_hmat->property = HMatrixSupport::Property::general;
5171 }
5172
5173 break;
5174 }
5175 case HMatrixSupport::Property::upper_triangular: {
5182 if (child_hmat->block_type ==
5183 HMatrixSupport::BlockType::diagonal_block)
5184 {
5185 child_hmat->property =
5186 HMatrixSupport::Property::upper_triangular;
5187 }
5188 else
5189 {
5190 child_hmat->property = HMatrixSupport::Property::general;
5191 }
5192
5193 break;
5194 }
5195 case HMatrixSupport::Property::lower_triangular: {
5202 if (child_hmat->block_type ==
5203 HMatrixSupport::BlockType::diagonal_block)
5204 {
5205 child_hmat->property =
5206 HMatrixSupport::Property::lower_triangular;
5207 }
5208 else
5209 {
5210 child_hmat->property = HMatrixSupport::Property::general;
5211 }
5212
5213 break;
5214 }
5215 default: {
5216 Assert(false,
5217 ExcMessage("Invalid H-matrix property: " +
5218 std::to_string(hmat->property)));
5219 break;
5220 }
5221 }
5222
5224 bc_node->get_child_pointer(i),
5225 fixed_rank_k,
5226 top_hmat_node_property);
5227
5231 hmat->submatrices.push_back(child_hmat);
5232
5237 child_hmat->parent = hmat;
5238
5239 child_hmat->submatrix_index = i;
5240 }
5241 }
5242 else
5243 {
5253 switch (top_hmat_node_property)
5254 {
5255 case HMatrixSupport::Property::general: {
5261 if (bc_node->get_data_reference().get_is_near_field())
5262 {
5263 hmat->type = FullMatrixType;
5264 hmat->fullmatrix =
5265 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5266 }
5267 else
5268 {
5269 hmat->type = RkMatrixType;
5270 hmat->rkmatrix =
5271 new RkMatrix<Number>(hmat->m, hmat->n, fixed_rank_k);
5272 }
5273
5274 break;
5275 }
5276 case HMatrixSupport::Property::symmetric: {
5283 switch (hmat->block_type)
5284 {
5285 case HMatrixSupport::BlockType::diagonal_block: {
5299 Assert(
5300 bc_node->get_data_reference().get_is_near_field(),
5301 ExcMessage(
5302 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
5308 Assert(
5309 hmat->property == top_hmat_node_property,
5310 ExcMessage(
5311 "A diagonal block should have the same property as that of the top level H-matrix node!"));
5312
5313 hmat->type = FullMatrixType;
5314 hmat->fullmatrix =
5315 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5316 hmat->fullmatrix->set_property(
5317 LAPACKSupport::Property::symmetric);
5318
5319 break;
5320 }
5321 case HMatrixSupport::BlockType::lower_triangular_block: {
5329 if (bc_node->get_data_reference().get_is_near_field())
5330 {
5331 hmat->type = FullMatrixType;
5332 hmat->fullmatrix =
5333 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5334 }
5335 else
5336 {
5337 hmat->type = RkMatrixType;
5338 hmat->rkmatrix = new RkMatrix<Number>(hmat->m,
5339 hmat->n,
5340 fixed_rank_k);
5341 }
5342
5343 break;
5344 }
5345 case HMatrixSupport::BlockType::upper_triangular_block: {
5353 if (bc_node->get_data_reference().get_is_near_field())
5354 {
5355 hmat->type = FullMatrixType;
5357 }
5358 else
5359 {
5360 hmat->type = RkMatrixType;
5361 hmat->rkmatrix =
5362 new RkMatrix<Number>(hmat->m, hmat->n, 0);
5363 }
5364
5365 break;
5366 }
5367 default: {
5368 Assert(false,
5369 ExcMessage(
5370 std::string("Invalid H-matrix block type: ") +
5371 std::string(HMatrixSupport::block_type_name(
5372 hmat->block_type))));
5373 break;
5374 }
5375 }
5376
5377 break;
5378 }
5379 case HMatrixSupport::Property::hermite_symmetric: {
5386 switch (hmat->block_type)
5387 {
5388 case HMatrixSupport::BlockType::diagonal_block: {
5402 Assert(
5403 bc_node->get_data_reference().get_is_near_field(),
5404 ExcMessage(
5405 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
5411 Assert(
5412 hmat->property == top_hmat_node_property,
5413 ExcMessage(
5414 "A diagonal block should have the same property as that of the top level H-matrix node!"));
5415
5416 hmat->type = FullMatrixType;
5417 hmat->fullmatrix =
5418 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5419 hmat->fullmatrix->set_property(
5420 LAPACKSupport::Property::hermite_symmetric);
5421
5422 break;
5423 }
5424 case HMatrixSupport::BlockType::lower_triangular_block: {
5432 if (bc_node->get_data_reference().get_is_near_field())
5433 {
5434 hmat->type = FullMatrixType;
5435 hmat->fullmatrix =
5436 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5437 }
5438 else
5439 {
5440 hmat->type = RkMatrixType;
5441 hmat->rkmatrix = new RkMatrix<Number>(hmat->m,
5442 hmat->n,
5443 fixed_rank_k);
5444 }
5445
5446 break;
5447 }
5448 case HMatrixSupport::BlockType::upper_triangular_block: {
5456 if (bc_node->get_data_reference().get_is_near_field())
5457 {
5458 hmat->type = FullMatrixType;
5460 }
5461 else
5462 {
5463 hmat->type = RkMatrixType;
5464 hmat->rkmatrix =
5465 new RkMatrix<Number>(hmat->m, hmat->n, 0);
5466 }
5467
5468 break;
5469 }
5470 default: {
5471 Assert(false,
5472 ExcMessage(
5473 std::string("Invalid H-matrix block type: ") +
5474 std::string(HMatrixSupport::block_type_name(
5475 hmat->block_type))));
5476 break;
5477 }
5478 }
5479
5480 break;
5481 }
5482 case HMatrixSupport::Property::lower_triangular: {
5489 switch (hmat->block_type)
5490 {
5491 case HMatrixSupport::BlockType::diagonal_block: {
5505 Assert(
5506 bc_node->get_data_reference().get_is_near_field(),
5507 ExcMessage(
5508 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
5514 Assert(
5515 hmat->property == top_hmat_node_property,
5516 ExcMessage(
5517 "A diagonal block should have the same property as that of the top level H-matrix node!"));
5518
5519 hmat->type = FullMatrixType;
5520 hmat->fullmatrix =
5521 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5522 hmat->fullmatrix->set_property(
5523 LAPACKSupport::Property::lower_triangular);
5524
5525 break;
5526 }
5527 case HMatrixSupport::BlockType::lower_triangular_block: {
5535 if (bc_node->get_data_reference().get_is_near_field())
5536 {
5537 hmat->type = FullMatrixType;
5538 hmat->fullmatrix =
5539 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5540 }
5541 else
5542 {
5543 hmat->type = RkMatrixType;
5544 hmat->rkmatrix = new RkMatrix<Number>(hmat->m,
5545 hmat->n,
5546 fixed_rank_k);
5547 }
5548
5549 break;
5550 }
5551 case HMatrixSupport::BlockType::upper_triangular_block: {
5558 if (bc_node->get_data_reference().get_is_near_field())
5559 {
5560 hmat->type = FullMatrixType;
5562 }
5563 else
5564 {
5565 hmat->type = RkMatrixType;
5566 hmat->rkmatrix =
5567 new RkMatrix<Number>(hmat->m, hmat->n, 0);
5568 }
5569
5570 break;
5571 }
5572 default: {
5573 Assert(false,
5574 ExcMessage(
5575 std::string("Invalid H-matrix block type: ") +
5576 std::string(HMatrixSupport::block_type_name(
5577 hmat->block_type))));
5578 break;
5579 }
5580 }
5581
5582 break;
5583 }
5584 case HMatrixSupport::Property::upper_triangular: {
5591 switch (hmat->block_type)
5592 {
5593 case HMatrixSupport::BlockType::diagonal_block: {
5607 Assert(
5608 bc_node->get_data_reference().get_is_near_field(),
5609 ExcMessage(
5610 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
5616 Assert(
5617 hmat->property == top_hmat_node_property,
5618 ExcMessage(
5619 "A diagonal block should have the same property as that of the top level H-matrix node!"));
5620
5621 hmat->type = FullMatrixType;
5622 hmat->fullmatrix =
5623 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5624 hmat->fullmatrix->set_property(
5625 LAPACKSupport::Property::upper_triangular);
5626
5627 break;
5628 }
5629 case HMatrixSupport::BlockType::upper_triangular_block: {
5637 if (bc_node->get_data_reference().get_is_near_field())
5638 {
5639 hmat->type = FullMatrixType;
5640 hmat->fullmatrix =
5641 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
5642 }
5643 else
5644 {
5645 hmat->type = RkMatrixType;
5646 hmat->rkmatrix = new RkMatrix<Number>(hmat->m,
5647 hmat->n,
5648 fixed_rank_k);
5649 }
5650
5651 break;
5652 }
5653 case HMatrixSupport::BlockType::lower_triangular_block: {
5660 if (bc_node->get_data_reference().get_is_near_field())
5661 {
5662 hmat->type = FullMatrixType;
5664 }
5665 else
5666 {
5667 hmat->type = RkMatrixType;
5668 hmat->rkmatrix =
5669 new RkMatrix<Number>(hmat->m, hmat->n, 0);
5670 }
5671
5672 break;
5673 }
5674 default: {
5675 Assert(false,
5676 ExcMessage(
5677 std::string("Invalid H-matrix block type: ") +
5678 std::string(HMatrixSupport::block_type_name(
5679 hmat->block_type))));
5680 break;
5681 }
5682 }
5683
5684 break;
5685 }
5686 default: {
5687 Assert(false,
5688 ExcMessage(
5689 std::string(
5690 "Invalid property of the top level H-matrix node: ") +
5691 std::string(HMatrixSupport::property_name(
5692 top_hmat_node_property))));
5693 break;
5694 }
5695 }
5696 }
5697}
5698
5699
5724template <int spacedim, typename Number = double>
5725void
5728 typename BlockClusterTree<spacedim,
5729 typename numbers::NumberTraits<Number>::real_type>::
5730 node_const_pointer_type bc_node,
5731 const unsigned int fixed_rank_k,
5733 const HMatrixSupport::Property top_hmat_node_property =
5734 HMatrixSupport::Property::general)
5735{
5739 hmat->bc_node = const_cast<typename BlockClusterTree<
5740 spacedim,
5741 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
5742 bc_node);
5743
5747 hmat->row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
5748 &(hmat->bc_node->get_data_reference()
5749 .get_tau_node()
5750 ->get_data_reference()
5751 .get_index_range()));
5752 hmat->col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
5753 &(hmat->bc_node->get_data_reference()
5754 .get_sigma_node()
5755 ->get_data_reference()
5756 .get_index_range()));
5757
5761 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
5762 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
5763
5764 const unsigned int bc_node_child_num = bc_node->get_child_num();
5765
5766 if (bc_node_child_num > 0)
5767 {
5774
5775 for (unsigned int i = 0; i < bc_node_child_num; i++)
5776 {
5780 HMatrix<spacedim, Number> *child_hmat =
5782
5787 child_hmat->state = hmat->state;
5788
5793 switch (hmat->block_type)
5794 {
5795 case HMatrixSupport::BlockType::undefined_block: {
5800 child_hmat->block_type = hmat->block_type;
5801
5802 break;
5803 }
5804 case HMatrixSupport::BlockType::diagonal_block: {
5811 switch (i)
5812 {
5813 case 0: {
5814 child_hmat->block_type =
5815 HMatrixSupport::BlockType::diagonal_block;
5816
5817 break;
5818 }
5819 case 1: {
5820 child_hmat->block_type =
5821 HMatrixSupport::BlockType::upper_triangular_block;
5822
5823 break;
5824 }
5825 case 2: {
5826 child_hmat->block_type =
5827 HMatrixSupport::BlockType::lower_triangular_block;
5828
5829 break;
5830 }
5831 case 3: {
5832 child_hmat->block_type =
5833 HMatrixSupport::BlockType::diagonal_block;
5834
5835 break;
5836 }
5837 default: {
5838 Assert(false, ExcNotImplemented());
5839 break;
5840 }
5841 }
5842
5843 break;
5844 }
5845 case HMatrixSupport::BlockType::upper_triangular_block: {
5850 child_hmat->block_type = hmat->block_type;
5851
5852 break;
5853 }
5854 case HMatrixSupport::BlockType::lower_triangular_block: {
5859 child_hmat->block_type = hmat->block_type;
5860
5861 break;
5862 }
5863 default: {
5864 Assert(false, ExcInvalidHMatrixBlockType(hmat->block_type));
5865 break;
5866 }
5867 }
5868
5873 switch (hmat->property)
5874 {
5875 case HMatrixSupport::Property::general: {
5880 child_hmat->property = HMatrixSupport::Property::general;
5881
5882 break;
5883 }
5884 case HMatrixSupport::Property::symmetric: {
5890 if (child_hmat->block_type ==
5891 HMatrixSupport::BlockType::diagonal_block)
5892 {
5893 child_hmat->property =
5894 HMatrixSupport::Property::symmetric;
5895 }
5896 else
5897 {
5898 child_hmat->property = HMatrixSupport::Property::general;
5899 }
5900
5901 break;
5902 }
5903 case HMatrixSupport::Property::hermite_symmetric: {
5909 if (child_hmat->block_type ==
5910 HMatrixSupport::BlockType::diagonal_block)
5911 {
5912 child_hmat->property =
5913 HMatrixSupport::Property::hermite_symmetric;
5914 }
5915 else
5916 {
5917 child_hmat->property = HMatrixSupport::Property::general;
5918 }
5919
5920 break;
5921 }
5922 case HMatrixSupport::Property::upper_triangular: {
5929 if (child_hmat->block_type ==
5930 HMatrixSupport::BlockType::diagonal_block)
5931 {
5932 child_hmat->property =
5933 HMatrixSupport::Property::upper_triangular;
5934 }
5935 else
5936 {
5937 child_hmat->property = HMatrixSupport::Property::general;
5938 }
5939
5940 break;
5941 }
5942 case HMatrixSupport::Property::lower_triangular: {
5949 if (child_hmat->block_type ==
5950 HMatrixSupport::BlockType::diagonal_block)
5951 {
5952 child_hmat->property =
5953 HMatrixSupport::Property::lower_triangular;
5954 }
5955 else
5956 {
5957 child_hmat->property = HMatrixSupport::Property::general;
5958 }
5959
5960 break;
5961 }
5962 default: {
5963 Assert(false, ExcInvalidHMatrixProperty(hmat->property));
5964 break;
5965 }
5966 }
5967
5969 bc_node->get_child_pointer(i),
5970 fixed_rank_k,
5971 M,
5972 top_hmat_node_property);
5973
5977 hmat->submatrices.push_back(child_hmat);
5978
5983 child_hmat->parent = hmat;
5984
5985 child_hmat->submatrix_index = i;
5986 }
5987 }
5988 else
5989 {
5999 switch (top_hmat_node_property)
6000 {
6001 case HMatrixSupport::Property::general: {
6007 if (bc_node->get_data_reference().get_is_near_field())
6008 {
6009 hmat->type = FullMatrixType;
6010 hmat->fullmatrix =
6011 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6012
6016 for (unsigned int i = 0; i < hmat->m; i++)
6017 {
6018 for (unsigned int j = 0; j < hmat->n; j++)
6019 {
6020 (*hmat->fullmatrix)(i, j) =
6021 M((*hmat->row_index_range)[0] + i,
6022 (*hmat->col_index_range)[0] + j);
6023 }
6024 }
6025 }
6026 else
6027 {
6028 hmat->type = RkMatrixType;
6029 hmat->rkmatrix =
6030 new RkMatrix<Number>(*(hmat->row_index_range),
6031 *(hmat->col_index_range),
6032 fixed_rank_k,
6033 M);
6034 }
6035
6036 break;
6037 }
6038 case HMatrixSupport::Property::symmetric: {
6045 switch (hmat->block_type)
6046 {
6047 case HMatrixSupport::BlockType::diagonal_block: {
6061 Assert(
6062 bc_node->get_data_reference().get_is_near_field(),
6063 ExcMessage(
6064 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
6070 Assert(
6071 hmat->property == top_hmat_node_property,
6072 ExcMessage(
6073 "A diagonal block should have the same property as that of the top level H-matrix node!"));
6074
6075 hmat->type = FullMatrixType;
6076 hmat->fullmatrix =
6077 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6078 hmat->fullmatrix->set_property(
6079 LAPACKSupport::Property::symmetric);
6080
6084 for (unsigned int i = 0; i < hmat->m; i++)
6085 {
6086 for (unsigned int j = 0; j < hmat->n; j++)
6087 {
6088 (*hmat->fullmatrix)(i, j) =
6089 M((*hmat->row_index_range)[0] + i,
6090 (*hmat->col_index_range)[0] + j);
6091 }
6092 }
6093
6094 break;
6095 }
6096 case HMatrixSupport::BlockType::lower_triangular_block: {
6104 if (bc_node->get_data_reference().get_is_near_field())
6105 {
6106 hmat->type = FullMatrixType;
6107 hmat->fullmatrix =
6108 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6109
6113 for (unsigned int i = 0; i < hmat->m; i++)
6114 {
6115 for (unsigned int j = 0; j < hmat->n; j++)
6116 {
6117 (*hmat->fullmatrix)(i, j) =
6118 M((*hmat->row_index_range)[0] + i,
6119 (*hmat->col_index_range)[0] + j);
6120 }
6121 }
6122 }
6123 else
6124 {
6125 hmat->type = RkMatrixType;
6126 hmat->rkmatrix =
6127 new RkMatrix<Number>(*(hmat->row_index_range),
6128 *(hmat->col_index_range),
6129 fixed_rank_k,
6130 M);
6131 }
6132
6133 break;
6134 }
6135 case HMatrixSupport::BlockType::upper_triangular_block: {
6143 if (bc_node->get_data_reference().get_is_near_field())
6144 {
6145 hmat->type = FullMatrixType;
6147 }
6148 else
6149 {
6150 hmat->type = RkMatrixType;
6151 hmat->rkmatrix =
6152 new RkMatrix<Number>(hmat->m, hmat->n, 0);
6153 }
6154
6155 break;
6156 }
6157 default: {
6158 Assert(false,
6159 ExcMessage(
6160 std::string("Invalid H-matrix block type: ") +
6161 std::string(HMatrixSupport::block_type_name(
6162 hmat->block_type))));
6163 break;
6164 }
6165 }
6166
6167 break;
6168 }
6169 case HMatrixSupport::Property::hermite_symmetric: {
6176 switch (hmat->block_type)
6177 {
6178 case HMatrixSupport::BlockType::diagonal_block: {
6192 Assert(
6193 bc_node->get_data_reference().get_is_near_field(),
6194 ExcMessage(
6195 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
6201 Assert(
6202 hmat->property == top_hmat_node_property,
6203 ExcMessage(
6204 "A diagonal block should have the same property as that of the top level H-matrix node!"));
6205
6206 hmat->type = FullMatrixType;
6207 hmat->fullmatrix =
6208 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6209 hmat->fullmatrix->set_property(
6210 LAPACKSupport::Property::hermite_symmetric);
6211
6215 for (unsigned int i = 0; i < hmat->m; i++)
6216 {
6217 for (unsigned int j = 0; j < hmat->n; j++)
6218 {
6219 (*hmat->fullmatrix)(i, j) =
6220 M((*hmat->row_index_range)[0] + i,
6221 (*hmat->col_index_range)[0] + j);
6222 }
6223 }
6224
6225 break;
6226 }
6227 case HMatrixSupport::BlockType::lower_triangular_block: {
6235 if (bc_node->get_data_reference().get_is_near_field())
6236 {
6237 hmat->type = FullMatrixType;
6238 hmat->fullmatrix =
6239 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6240
6244 for (unsigned int i = 0; i < hmat->m; i++)
6245 {
6246 for (unsigned int j = 0; j < hmat->n; j++)
6247 {
6248 (*hmat->fullmatrix)(i, j) =
6249 M((*hmat->row_index_range)[0] + i,
6250 (*hmat->col_index_range)[0] + j);
6251 }
6252 }
6253 }
6254 else
6255 {
6256 hmat->type = RkMatrixType;
6257 hmat->rkmatrix =
6258 new RkMatrix<Number>(*(hmat->row_index_range),
6259 *(hmat->col_index_range),
6260 fixed_rank_k,
6261 M);
6262 }
6263
6264 break;
6265 }
6266 case HMatrixSupport::BlockType::upper_triangular_block: {
6274 if (bc_node->get_data_reference().get_is_near_field())
6275 {
6276 hmat->type = FullMatrixType;
6278 }
6279 else
6280 {
6281 hmat->type = RkMatrixType;
6282 hmat->rkmatrix =
6283 new RkMatrix<Number>(hmat->m, hmat->n, 0);
6284 }
6285
6286 break;
6287 }
6288 default: {
6289 Assert(false,
6290 ExcMessage(
6291 std::string("Invalid H-matrix block type: ") +
6292 std::string(HMatrixSupport::block_type_name(
6293 hmat->block_type))));
6294 break;
6295 }
6296 }
6297
6298 break;
6299 }
6300 case HMatrixSupport::Property::lower_triangular: {
6307 switch (hmat->block_type)
6308 {
6309 case HMatrixSupport::BlockType::diagonal_block: {
6323 Assert(
6324 bc_node->get_data_reference().get_is_near_field(),
6325 ExcMessage(
6326 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
6332 Assert(
6333 hmat->property == top_hmat_node_property,
6334 ExcMessage(
6335 "A diagonal block should have the same property as that of the top level H-matrix node!"));
6336
6337 hmat->type = FullMatrixType;
6338 hmat->fullmatrix =
6339 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6340 hmat->fullmatrix->set_property(
6341 LAPACKSupport::Property::lower_triangular);
6342
6346 for (unsigned int i = 0; i < hmat->m; i++)
6347 {
6348 for (unsigned int j = 0; j < hmat->n; j++)
6349 {
6350 (*hmat->fullmatrix)(i, j) =
6351 M((*hmat->row_index_range)[0] + i,
6352 (*hmat->col_index_range)[0] + j);
6353 }
6354 }
6355
6356 break;
6357 }
6358 case HMatrixSupport::BlockType::lower_triangular_block: {
6366 if (bc_node->get_data_reference().get_is_near_field())
6367 {
6368 hmat->type = FullMatrixType;
6369 hmat->fullmatrix =
6370 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6371
6375 for (unsigned int i = 0; i < hmat->m; i++)
6376 {
6377 for (unsigned int j = 0; j < hmat->n; j++)
6378 {
6379 (*hmat->fullmatrix)(i, j) =
6380 M((*hmat->row_index_range)[0] + i,
6381 (*hmat->col_index_range)[0] + j);
6382 }
6383 }
6384 }
6385 else
6386 {
6387 hmat->type = RkMatrixType;
6388 hmat->rkmatrix =
6389 new RkMatrix<Number>(*(hmat->row_index_range),
6390 *(hmat->col_index_range),
6391 fixed_rank_k,
6392 M);
6393 }
6394
6395 break;
6396 }
6397 case HMatrixSupport::BlockType::upper_triangular_block: {
6404 if (bc_node->get_data_reference().get_is_near_field())
6405 {
6406 hmat->type = FullMatrixType;
6408 }
6409 else
6410 {
6411 hmat->type = RkMatrixType;
6412 hmat->rkmatrix =
6413 new RkMatrix<Number>(hmat->m, hmat->n, 0);
6414 }
6415
6416 break;
6417 }
6418 default: {
6419 Assert(false,
6420 ExcMessage(
6421 std::string("Invalid H-matrix block type: ") +
6422 std::string(HMatrixSupport::block_type_name(
6423 hmat->block_type))));
6424 break;
6425 }
6426 }
6427
6428 break;
6429 }
6430 case HMatrixSupport::Property::upper_triangular: {
6437 switch (hmat->block_type)
6438 {
6439 case HMatrixSupport::BlockType::diagonal_block: {
6453 Assert(
6454 bc_node->get_data_reference().get_is_near_field(),
6455 ExcMessage(
6456 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
6462 Assert(
6463 hmat->property == top_hmat_node_property,
6464 ExcMessage(
6465 "A diagonal block should have the same property as that of the top level H-matrix node!"));
6466
6467 hmat->type = FullMatrixType;
6468 hmat->fullmatrix =
6469 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6470 hmat->fullmatrix->set_property(
6471 LAPACKSupport::Property::upper_triangular);
6472
6476 for (unsigned int i = 0; i < hmat->m; i++)
6477 {
6478 for (unsigned int j = 0; j < hmat->n; j++)
6479 {
6480 (*hmat->fullmatrix)(i, j) =
6481 M((*hmat->row_index_range)[0] + i,
6482 (*hmat->col_index_range)[0] + j);
6483 }
6484 }
6485
6486 break;
6487 }
6488 case HMatrixSupport::BlockType::upper_triangular_block: {
6496 if (bc_node->get_data_reference().get_is_near_field())
6497 {
6498 hmat->type = FullMatrixType;
6499 hmat->fullmatrix =
6500 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6501
6505 for (unsigned int i = 0; i < hmat->m; i++)
6506 {
6507 for (unsigned int j = 0; j < hmat->n; j++)
6508 {
6509 (*hmat->fullmatrix)(i, j) =
6510 M((*hmat->row_index_range)[0] + i,
6511 (*hmat->col_index_range)[0] + j);
6512 }
6513 }
6514 }
6515 else
6516 {
6517 hmat->type = RkMatrixType;
6518 hmat->rkmatrix =
6519 new RkMatrix<Number>(*(hmat->row_index_range),
6520 *(hmat->col_index_range),
6521 fixed_rank_k,
6522 M);
6523 }
6524
6525 break;
6526 }
6527 case HMatrixSupport::BlockType::lower_triangular_block: {
6534 if (bc_node->get_data_reference().get_is_near_field())
6535 {
6536 hmat->type = FullMatrixType;
6538 }
6539 else
6540 {
6541 hmat->type = RkMatrixType;
6542 hmat->rkmatrix =
6543 new RkMatrix<Number>(hmat->m, hmat->n, 0);
6544 }
6545
6546 break;
6547 }
6548 default: {
6549 Assert(false,
6550 ExcMessage(
6551 std::string("Invalid H-matrix block type: ") +
6552 std::string(HMatrixSupport::block_type_name(
6553 hmat->block_type))));
6554 break;
6555 }
6556 }
6557
6558 break;
6559 }
6560 default: {
6561 Assert(false,
6562 ExcMessage(
6563 std::string(
6564 "Invalid property of the top level H-matrix node: ") +
6565 std::string(HMatrixSupport::property_name(
6566 top_hmat_node_property))));
6567 break;
6568 }
6569 }
6570 }
6571}
6572
6573
6599template <int spacedim, typename Number = double>
6600void
6603 typename BlockClusterTree<spacedim,
6604 typename numbers::NumberTraits<Number>::real_type>::
6605 node_const_pointer_type bc_node,
6607 const HMatrixSupport::Property top_hmat_node_property =
6608 HMatrixSupport::Property::general)
6609{
6613 hmat->bc_node = const_cast<typename BlockClusterTree<
6614 spacedim,
6615 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
6616 bc_node);
6617
6621 hmat->row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
6622 &(hmat->bc_node->get_data_reference()
6623 .get_tau_node()
6624 ->get_data_reference()
6625 .get_index_range()));
6626 hmat->col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
6627 &(hmat->bc_node->get_data_reference()
6628 .get_sigma_node()
6629 ->get_data_reference()
6630 .get_index_range()));
6631
6635 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
6636 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
6637
6638 const unsigned int bc_node_child_num = bc_node->get_child_num();
6639
6640 if (bc_node_child_num > 0)
6641 {
6648
6649 for (unsigned int i = 0; i < bc_node_child_num; i++)
6650 {
6654 HMatrix<spacedim, Number> *child_hmat =
6656
6661 child_hmat->state = hmat->state;
6662
6667 switch (hmat->block_type)
6668 {
6669 case HMatrixSupport::BlockType::undefined_block: {
6674 child_hmat->block_type = hmat->block_type;
6675
6676 break;
6677 }
6678 case HMatrixSupport::BlockType::diagonal_block: {
6685 switch (i)
6686 {
6687 case 0: {
6688 child_hmat->block_type =
6689 HMatrixSupport::BlockType::diagonal_block;
6690
6691 break;
6692 }
6693 case 1: {
6694 child_hmat->block_type =
6695 HMatrixSupport::BlockType::upper_triangular_block;
6696
6697 break;
6698 }
6699 case 2: {
6700 child_hmat->block_type =
6701 HMatrixSupport::BlockType::lower_triangular_block;
6702
6703 break;
6704 }
6705 case 3: {
6706 child_hmat->block_type =
6707 HMatrixSupport::BlockType::diagonal_block;
6708
6709 break;
6710 }
6711 default: {
6712 Assert(false, ExcNotImplemented());
6713 break;
6714 }
6715 }
6716
6717 break;
6718 }
6719 case HMatrixSupport::BlockType::upper_triangular_block: {
6724 child_hmat->block_type = hmat->block_type;
6725
6726 break;
6727 }
6728 case HMatrixSupport::BlockType::lower_triangular_block: {
6733 child_hmat->block_type = hmat->block_type;
6734
6735 break;
6736 }
6737 default: {
6738 Assert(false,
6739 ExcMessage("Invalid H-matrix block type: " +
6740 std::to_string(hmat->block_type)));
6741 break;
6742 }
6743 }
6744
6749 switch (hmat->property)
6750 {
6751 case HMatrixSupport::Property::general: {
6756 child_hmat->property = HMatrixSupport::Property::general;
6757
6758 break;
6759 }
6760 case HMatrixSupport::Property::symmetric: {
6766 if (child_hmat->block_type ==
6767 HMatrixSupport::BlockType::diagonal_block)
6768 {
6769 child_hmat->property =
6770 HMatrixSupport::Property::symmetric;
6771 }
6772 else
6773 {
6774 child_hmat->property = HMatrixSupport::Property::general;
6775 }
6776
6777 break;
6778 }
6779 case HMatrixSupport::Property::hermite_symmetric: {
6785 if (child_hmat->block_type ==
6786 HMatrixSupport::BlockType::diagonal_block)
6787 {
6788 child_hmat->property =
6789 HMatrixSupport::Property::hermite_symmetric;
6790 }
6791 else
6792 {
6793 child_hmat->property = HMatrixSupport::Property::general;
6794 }
6795
6796 break;
6797 }
6798 case HMatrixSupport::Property::upper_triangular: {
6805 if (child_hmat->block_type ==
6806 HMatrixSupport::BlockType::diagonal_block)
6807 {
6808 child_hmat->property =
6809 HMatrixSupport::Property::upper_triangular;
6810 }
6811 else
6812 {
6813 child_hmat->property = HMatrixSupport::Property::general;
6814 }
6815
6816 break;
6817 }
6818 case HMatrixSupport::Property::lower_triangular: {
6825 if (child_hmat->block_type ==
6826 HMatrixSupport::BlockType::diagonal_block)
6827 {
6828 child_hmat->property =
6829 HMatrixSupport::Property::lower_triangular;
6830 }
6831 else
6832 {
6833 child_hmat->property = HMatrixSupport::Property::general;
6834 }
6835
6836 break;
6837 }
6838 default: {
6839 Assert(false,
6840 ExcMessage("Invalid H-matrix property: " +
6841 std::to_string(hmat->property)));
6842 break;
6843 }
6844 }
6845
6847 bc_node->get_child_pointer(i),
6848 M,
6849 top_hmat_node_property);
6850
6854 hmat->submatrices.push_back(child_hmat);
6855
6860 child_hmat->parent = hmat;
6861
6862 child_hmat->submatrix_index = i;
6863 }
6864 }
6865 else
6866 {
6876 switch (top_hmat_node_property)
6877 {
6878 case HMatrixSupport::Property::general: {
6884 if (bc_node->get_data_reference().get_is_near_field())
6885 {
6886 hmat->type = FullMatrixType;
6887 hmat->fullmatrix =
6888 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6889
6893 for (unsigned int i = 0; i < hmat->m; i++)
6894 {
6895 for (unsigned int j = 0; j < hmat->n; j++)
6896 {
6897 (*hmat->fullmatrix)(i, j) =
6898 M((*hmat->row_index_range)[0] + i,
6899 (*hmat->col_index_range)[0] + j);
6900 }
6901 }
6902 }
6903 else
6904 {
6905 hmat->type = RkMatrixType;
6906 hmat->rkmatrix =
6907 new RkMatrix<Number>(*(hmat->row_index_range),
6908 *(hmat->col_index_range),
6909 M);
6910 }
6911
6912 break;
6913 }
6914 case HMatrixSupport::Property::symmetric: {
6921 switch (hmat->block_type)
6922 {
6923 case HMatrixSupport::BlockType::diagonal_block: {
6937 Assert(
6938 bc_node->get_data_reference().get_is_near_field(),
6939 ExcMessage(
6940 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
6946 Assert(
6947 hmat->property == top_hmat_node_property,
6948 ExcMessage(
6949 "A diagonal block should have the same property as that of the top level H-matrix node!"));
6950
6951 hmat->type = FullMatrixType;
6952 hmat->fullmatrix =
6953 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6954 hmat->fullmatrix->set_property(
6955 LAPACKSupport::Property::symmetric);
6956
6960 for (unsigned int i = 0; i < hmat->m; i++)
6961 {
6962 for (unsigned int j = 0; j < hmat->n; j++)
6963 {
6964 (*hmat->fullmatrix)(i, j) =
6965 M((*hmat->row_index_range)[0] + i,
6966 (*hmat->col_index_range)[0] + j);
6967 }
6968 }
6969
6970 break;
6971 }
6972 case HMatrixSupport::BlockType::lower_triangular_block: {
6980 if (bc_node->get_data_reference().get_is_near_field())
6981 {
6982 hmat->type = FullMatrixType;
6983 hmat->fullmatrix =
6984 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
6985
6989 for (unsigned int i = 0; i < hmat->m; i++)
6990 {
6991 for (unsigned int j = 0; j < hmat->n; j++)
6992 {
6993 (*hmat->fullmatrix)(i, j) =
6994 M((*hmat->row_index_range)[0] + i,
6995 (*hmat->col_index_range)[0] + j);
6996 }
6997 }
6998 }
6999 else
7000 {
7001 hmat->type = RkMatrixType;
7002 hmat->rkmatrix =
7003 new RkMatrix<Number>(*(hmat->row_index_range),
7004 *(hmat->col_index_range),
7005 M);
7006 }
7007
7008 break;
7009 }
7010 case HMatrixSupport::BlockType::upper_triangular_block: {
7018 if (bc_node->get_data_reference().get_is_near_field())
7019 {
7020 hmat->type = FullMatrixType;
7022 }
7023 else
7024 {
7025 hmat->type = RkMatrixType;
7026 hmat->rkmatrix =
7027 new RkMatrix<Number>(hmat->m, hmat->n, 0);
7028 }
7029
7030 break;
7031 }
7032 default: {
7033 Assert(false,
7034 ExcInvalidHMatrixBlockType(hmat->block_type));
7035 break;
7036 }
7037 }
7038
7039 break;
7040 }
7041 case HMatrixSupport::Property::hermite_symmetric: {
7048 switch (hmat->block_type)
7049 {
7050 case HMatrixSupport::BlockType::diagonal_block: {
7064 Assert(
7065 bc_node->get_data_reference().get_is_near_field(),
7066 ExcMessage(
7067 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
7073 Assert(
7074 hmat->property == top_hmat_node_property,
7075 ExcMessage(
7076 "A diagonal block should have the same property as that of the top level H-matrix node!"));
7077
7078 hmat->type = FullMatrixType;
7079 hmat->fullmatrix =
7080 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7081 hmat->fullmatrix->set_property(
7082 LAPACKSupport::Property::hermite_symmetric);
7083
7087 for (unsigned int i = 0; i < hmat->m; i++)
7088 {
7089 for (unsigned int j = 0; j < hmat->n; j++)
7090 {
7091 (*hmat->fullmatrix)(i, j) =
7092 M((*hmat->row_index_range)[0] + i,
7093 (*hmat->col_index_range)[0] + j);
7094 }
7095 }
7096
7097 break;
7098 }
7099 case HMatrixSupport::BlockType::lower_triangular_block: {
7107 if (bc_node->get_data_reference().get_is_near_field())
7108 {
7109 hmat->type = FullMatrixType;
7110 hmat->fullmatrix =
7111 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7112
7116 for (unsigned int i = 0; i < hmat->m; i++)
7117 {
7118 for (unsigned int j = 0; j < hmat->n; j++)
7119 {
7120 (*hmat->fullmatrix)(i, j) =
7121 M((*hmat->row_index_range)[0] + i,
7122 (*hmat->col_index_range)[0] + j);
7123 }
7124 }
7125 }
7126 else
7127 {
7128 hmat->type = RkMatrixType;
7129 hmat->rkmatrix =
7130 new RkMatrix<Number>(*(hmat->row_index_range),
7131 *(hmat->col_index_range),
7132 M);
7133 }
7134
7135 break;
7136 }
7137 case HMatrixSupport::BlockType::upper_triangular_block: {
7145 if (bc_node->get_data_reference().get_is_near_field())
7146 {
7147 hmat->type = FullMatrixType;
7149 }
7150 else
7151 {
7152 hmat->type = RkMatrixType;
7153 hmat->rkmatrix =
7154 new RkMatrix<Number>(hmat->m, hmat->n, 0);
7155 }
7156
7157 break;
7158 }
7159 default: {
7160 Assert(false,
7161 ExcInvalidHMatrixBlockType(hmat->block_type));
7162 break;
7163 }
7164 }
7165
7166 break;
7167 }
7168 case HMatrixSupport::Property::lower_triangular: {
7175 switch (hmat->block_type)
7176 {
7177 case HMatrixSupport::BlockType::diagonal_block: {
7191 Assert(
7192 bc_node->get_data_reference().get_is_near_field(),
7193 ExcMessage(
7194 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
7200 Assert(
7201 hmat->property == top_hmat_node_property,
7202 ExcMessage(
7203 "A diagonal block should have the same property as that of the top level H-matrix node!"));
7204
7205 hmat->type = FullMatrixType;
7206 hmat->fullmatrix =
7207 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7208 hmat->fullmatrix->set_property(
7209 LAPACKSupport::Property::lower_triangular);
7210
7214 for (unsigned int i = 0; i < hmat->m; i++)
7215 {
7216 for (unsigned int j = 0; j < hmat->n; j++)
7217 {
7218 (*hmat->fullmatrix)(i, j) =
7219 M((*hmat->row_index_range)[0] + i,
7220 (*hmat->col_index_range)[0] + j);
7221 }
7222 }
7223
7224 break;
7225 }
7226 case HMatrixSupport::BlockType::lower_triangular_block: {
7234 if (bc_node->get_data_reference().get_is_near_field())
7235 {
7236 hmat->type = FullMatrixType;
7237 hmat->fullmatrix =
7238 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7239
7243 for (unsigned int i = 0; i < hmat->m; i++)
7244 {
7245 for (unsigned int j = 0; j < hmat->n; j++)
7246 {
7247 (*hmat->fullmatrix)(i, j) =
7248 M((*hmat->row_index_range)[0] + i,
7249 (*hmat->col_index_range)[0] + j);
7250 }
7251 }
7252 }
7253 else
7254 {
7255 hmat->type = RkMatrixType;
7256 hmat->rkmatrix =
7257 new RkMatrix<Number>(*(hmat->row_index_range),
7258 *(hmat->col_index_range),
7259 M);
7260 }
7261
7262 break;
7263 }
7264 case HMatrixSupport::BlockType::upper_triangular_block: {
7271 if (bc_node->get_data_reference().get_is_near_field())
7272 {
7273 hmat->type = FullMatrixType;
7275 }
7276 else
7277 {
7278 hmat->type = RkMatrixType;
7279 hmat->rkmatrix =
7280 new RkMatrix<Number>(hmat->m, hmat->n, 0);
7281 }
7282
7283 break;
7284 }
7285 default: {
7286 Assert(false,
7287 ExcInvalidHMatrixBlockType(hmat->block_type));
7288 break;
7289 }
7290 }
7291
7292 break;
7293 }
7294 case HMatrixSupport::Property::upper_triangular: {
7301 switch (hmat->block_type)
7302 {
7303 case HMatrixSupport::BlockType::diagonal_block: {
7317 Assert(
7318 bc_node->get_data_reference().get_is_near_field(),
7319 ExcMessage(
7320 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
7326 Assert(
7327 hmat->property == top_hmat_node_property,
7328 ExcMessage(
7329 "A diagonal block should have the same property as that of the top level H-matrix node!"));
7330
7331 hmat->type = FullMatrixType;
7332 hmat->fullmatrix =
7333 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7334 hmat->fullmatrix->set_property(
7335 LAPACKSupport::Property::upper_triangular);
7336
7340 for (unsigned int i = 0; i < hmat->m; i++)
7341 {
7342 for (unsigned int j = 0; j < hmat->n; j++)
7343 {
7344 (*hmat->fullmatrix)(i, j) =
7345 M((*hmat->row_index_range)[0] + i,
7346 (*hmat->col_index_range)[0] + j);
7347 }
7348 }
7349
7350 break;
7351 }
7352 case HMatrixSupport::BlockType::upper_triangular_block: {
7360 if (bc_node->get_data_reference().get_is_near_field())
7361 {
7362 hmat->type = FullMatrixType;
7363 hmat->fullmatrix =
7364 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7365
7369 for (unsigned int i = 0; i < hmat->m; i++)
7370 {
7371 for (unsigned int j = 0; j < hmat->n; j++)
7372 {
7373 (*hmat->fullmatrix)(i, j) =
7374 M((*hmat->row_index_range)[0] + i,
7375 (*hmat->col_index_range)[0] + j);
7376 }
7377 }
7378 }
7379 else
7380 {
7381 hmat->type = RkMatrixType;
7382 hmat->rkmatrix =
7383 new RkMatrix<Number>(*(hmat->row_index_range),
7384 *(hmat->col_index_range),
7385 M);
7386 }
7387
7388 break;
7389 }
7390 case HMatrixSupport::BlockType::lower_triangular_block: {
7397 if (bc_node->get_data_reference().get_is_near_field())
7398 {
7399 hmat->type = FullMatrixType;
7401 }
7402 else
7403 {
7404 hmat->type = RkMatrixType;
7405 hmat->rkmatrix =
7406 new RkMatrix<Number>(hmat->m, hmat->n, 0);
7407 }
7408
7409 break;
7410 }
7411 default: {
7412 Assert(false,
7413 ExcInvalidHMatrixBlockType(hmat->block_type));
7414 break;
7415 }
7416 }
7417
7418 break;
7419 }
7420 default: {
7421 Assert(false, ExcInvalidHMatrixProperty(top_hmat_node_property));
7422 break;
7423 }
7424 }
7425 }
7426}
7427
7428
7457template <int spacedim, typename Number = double>
7458void
7461 typename BlockClusterTree<spacedim,
7462 typename numbers::NumberTraits<Number>::real_type>::
7463 node_const_pointer_type bc_node,
7464 const unsigned int fixed_rank_k,
7466 const std::array<types::global_dof_index, 2> &M_row_index_range,
7467 const std::array<types::global_dof_index, 2> &M_col_index_range,
7468 const HMatrixSupport::Property top_hmat_node_property =
7469 HMatrixSupport::Property::general)
7470{
7474 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
7475 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
7476
7477 const unsigned int bc_node_child_num = bc_node->get_child_num();
7478
7479 if (bc_node_child_num > 0)
7480 {
7487
7488 for (unsigned int i = 0; i < bc_node_child_num; i++)
7489 {
7493 HMatrix<spacedim, Number> *child_hmat =
7495
7500 child_hmat->state = hmat->state;
7501
7506 switch (hmat->block_type)
7507 {
7508 case HMatrixSupport::BlockType::undefined_block: {
7513 child_hmat->block_type = hmat->block_type;
7514
7515 break;
7516 }
7517 case HMatrixSupport::BlockType::diagonal_block: {
7524 switch (i)
7525 {
7526 case 0: {
7527 child_hmat->block_type =
7528 HMatrixSupport::BlockType::diagonal_block;
7529
7530 break;
7531 }
7532 case 1: {
7533 child_hmat->block_type =
7534 HMatrixSupport::BlockType::upper_triangular_block;
7535
7536 break;
7537 }
7538 case 2: {
7539 child_hmat->block_type =
7540 HMatrixSupport::BlockType::lower_triangular_block;
7541
7542 break;
7543 }
7544 case 3: {
7545 child_hmat->block_type =
7546 HMatrixSupport::BlockType::diagonal_block;
7547
7548 break;
7549 }
7550 default: {
7551 Assert(false, ExcNotImplemented());
7552 break;
7553 }
7554 }
7555
7556 break;
7557 }
7558 case HMatrixSupport::BlockType::upper_triangular_block: {
7563 child_hmat->block_type = hmat->block_type;
7564
7565 break;
7566 }
7567 case HMatrixSupport::BlockType::lower_triangular_block: {
7572 child_hmat->block_type = hmat->block_type;
7573
7574 break;
7575 }
7576 default: {
7577 Assert(false, ExcInvalidHMatrixBlockType(hmat->block_type));
7578 break;
7579 }
7580 }
7581
7586 switch (hmat->property)
7587 {
7588 case HMatrixSupport::Property::general: {
7593 child_hmat->property = HMatrixSupport::Property::general;
7594
7595 break;
7596 }
7597 case HMatrixSupport::Property::symmetric: {
7603 if (child_hmat->block_type ==
7604 HMatrixSupport::BlockType::diagonal_block)
7605 {
7606 child_hmat->property =
7607 HMatrixSupport::Property::symmetric;
7608 }
7609 else
7610 {
7611 child_hmat->property = HMatrixSupport::Property::general;
7612 }
7613
7614 break;
7615 }
7616 case HMatrixSupport::Property::hermite_symmetric: {
7622 if (child_hmat->block_type ==
7623 HMatrixSupport::BlockType::diagonal_block)
7624 {
7625 child_hmat->property =
7626 HMatrixSupport::Property::hermite_symmetric;
7627 }
7628 else
7629 {
7630 child_hmat->property = HMatrixSupport::Property::general;
7631 }
7632
7633 break;
7634 }
7635 case HMatrixSupport::Property::upper_triangular: {
7642 if (child_hmat->block_type ==
7643 HMatrixSupport::BlockType::diagonal_block)
7644 {
7645 child_hmat->property =
7646 HMatrixSupport::Property::upper_triangular;
7647 }
7648 else
7649 {
7650 child_hmat->property = HMatrixSupport::Property::general;
7651 }
7652
7653 break;
7654 }
7655 case HMatrixSupport::Property::lower_triangular: {
7662 if (child_hmat->block_type ==
7663 HMatrixSupport::BlockType::diagonal_block)
7664 {
7665 child_hmat->property =
7666 HMatrixSupport::Property::lower_triangular;
7667 }
7668 else
7669 {
7670 child_hmat->property = HMatrixSupport::Property::general;
7671 }
7672
7673 break;
7674 }
7675 default: {
7676 Assert(false, ExcInvalidHMatrixProperty(hmat->property));
7677 break;
7678 }
7679 }
7680
7682 bc_node->get_child_pointer(i),
7683 fixed_rank_k,
7684 M,
7685 M_row_index_range,
7686 M_col_index_range,
7687 top_hmat_node_property);
7688
7692 hmat->submatrices.push_back(child_hmat);
7693
7698 child_hmat->parent = hmat;
7699
7700 child_hmat->submatrix_index = i;
7701 }
7702 }
7703 else
7704 {
7714 switch (top_hmat_node_property)
7715 {
7716 case HMatrixSupport::Property::general: {
7722 if (bc_node->get_data_reference().get_is_near_field())
7723 {
7724 hmat->type = FullMatrixType;
7725 hmat->fullmatrix =
7726 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7727
7731 for (unsigned int i = 0; i < hmat->m; i++)
7732 {
7733 for (unsigned int j = 0; j < hmat->n; j++)
7734 {
7735 (*hmat->fullmatrix)(i, j) =
7736 M((*hmat->row_index_range)[0] -
7737 M_row_index_range[0] + i,
7738 (*hmat->col_index_range)[0] -
7739 M_col_index_range[0] + j);
7740 }
7741 }
7742 }
7743 else
7744 {
7745 hmat->type = RkMatrixType;
7746 hmat->rkmatrix =
7747 new RkMatrix<Number>(*(hmat->row_index_range),
7748 *(hmat->col_index_range),
7749 fixed_rank_k,
7750 M,
7751 M_row_index_range,
7752 M_col_index_range);
7753 }
7754
7755 break;
7756 }
7757 case HMatrixSupport::Property::symmetric: {
7764 switch (hmat->block_type)
7765 {
7766 case HMatrixSupport::BlockType::diagonal_block: {
7780 Assert(
7781 bc_node->get_data_reference().get_is_near_field(),
7782 ExcMessage(
7783 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
7789 Assert(
7790 hmat->property == top_hmat_node_property,
7791 ExcMessage(
7792 "A diagonal block should have the same property as that of the top level H-matrix node!"));
7793
7794 hmat->type = FullMatrixType;
7795 hmat->fullmatrix =
7796 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7797 hmat->fullmatrix->set_property(
7798 LAPACKSupport::Property::symmetric);
7799
7803 for (unsigned int i = 0; i < hmat->m; i++)
7804 {
7805 for (unsigned int j = 0; j < hmat->n; j++)
7806 {
7807 (*hmat->fullmatrix)(i, j) =
7808 M((*hmat->row_index_range)[0] -
7809 M_row_index_range[0] + i,
7810 (*hmat->col_index_range)[0] -
7811 M_col_index_range[0] + j);
7812 }
7813 }
7814
7815 break;
7816 }
7817 case HMatrixSupport::BlockType::lower_triangular_block: {
7825 if (bc_node->get_data_reference().get_is_near_field())
7826 {
7827 hmat->type = FullMatrixType;
7828 hmat->fullmatrix =
7829 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7830
7834 for (unsigned int i = 0; i < hmat->m; i++)
7835 {
7836 for (unsigned int j = 0; j < hmat->n; j++)
7837 {
7838 (*hmat->fullmatrix)(i, j) =
7839 M((*hmat->row_index_range)[0] -
7840 M_row_index_range[0] + i,
7841 (*hmat->col_index_range)[0] -
7842 M_col_index_range[0] + j);
7843 }
7844 }
7845 }
7846 else
7847 {
7848 hmat->type = RkMatrixType;
7849 hmat->rkmatrix =
7850 new RkMatrix<Number>(*(hmat->row_index_range),
7851 *(hmat->col_index_range),
7852 fixed_rank_k,
7853 M,
7854 M_row_index_range,
7855 M_col_index_range);
7856 }
7857
7858 break;
7859 }
7860 case HMatrixSupport::BlockType::upper_triangular_block: {
7868 if (bc_node->get_data_reference().get_is_near_field())
7869 {
7870 hmat->type = FullMatrixType;
7872 }
7873 else
7874 {
7875 hmat->type = RkMatrixType;
7876 hmat->rkmatrix =
7877 new RkMatrix<Number>(hmat->m, hmat->n, 0);
7878 }
7879
7880 break;
7881 }
7882 default: {
7883 Assert(false,
7884 ExcInvalidHMatrixBlockType(hmat->block_type));
7885 break;
7886 }
7887 }
7888
7889 break;
7890 }
7891 case HMatrixSupport::Property::hermite_symmetric: {
7898 switch (hmat->block_type)
7899 {
7900 case HMatrixSupport::BlockType::diagonal_block: {
7914 Assert(
7915 bc_node->get_data_reference().get_is_near_field(),
7916 ExcMessage(
7917 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
7923 Assert(
7924 hmat->property == top_hmat_node_property,
7925 ExcMessage(
7926 "A diagonal block should have the same property as that of the top level H-matrix node!"));
7927
7928 hmat->type = FullMatrixType;
7929 hmat->fullmatrix =
7930 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7931 hmat->fullmatrix->set_property(
7932 LAPACKSupport::Property::hermite_symmetric);
7933
7937 for (unsigned int i = 0; i < hmat->m; i++)
7938 {
7939 for (unsigned int j = 0; j < hmat->n; j++)
7940 {
7941 (*hmat->fullmatrix)(i, j) =
7942 M((*hmat->row_index_range)[0] -
7943 M_row_index_range[0] + i,
7944 (*hmat->col_index_range)[0] -
7945 M_col_index_range[0] + j);
7946 }
7947 }
7948
7949 break;
7950 }
7951 case HMatrixSupport::BlockType::lower_triangular_block: {
7959 if (bc_node->get_data_reference().get_is_near_field())
7960 {
7961 hmat->type = FullMatrixType;
7962 hmat->fullmatrix =
7963 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
7964
7968 for (unsigned int i = 0; i < hmat->m; i++)
7969 {
7970 for (unsigned int j = 0; j < hmat->n; j++)
7971 {
7972 (*hmat->fullmatrix)(i, j) =
7973 M((*hmat->row_index_range)[0] -
7974 M_row_index_range[0] + i,
7975 (*hmat->col_index_range)[0] -
7976 M_col_index_range[0] + j);
7977 }
7978 }
7979 }
7980 else
7981 {
7982 hmat->type = RkMatrixType;
7983 hmat->rkmatrix =
7984 new RkMatrix<Number>(*(hmat->row_index_range),
7985 *(hmat->col_index_range),
7986 fixed_rank_k,
7987 M,
7988 M_row_index_range,
7989 M_col_index_range);
7990 }
7991
7992 break;
7993 }
7994 case HMatrixSupport::BlockType::upper_triangular_block: {
8002 if (bc_node->get_data_reference().get_is_near_field())
8003 {
8004 hmat->type = FullMatrixType;
8006 }
8007 else
8008 {
8009 hmat->type = RkMatrixType;
8010 hmat->rkmatrix =
8011 new RkMatrix<Number>(hmat->m, hmat->n, 0);
8012 }
8013
8014 break;
8015 }
8016 default: {
8017 Assert(false,
8018 ExcInvalidHMatrixBlockType(hmat->block_type));
8019 break;
8020 }
8021 }
8022
8023 break;
8024 }
8025 case HMatrixSupport::Property::lower_triangular: {
8032 switch (hmat->block_type)
8033 {
8034 case HMatrixSupport::BlockType::diagonal_block: {
8048 Assert(
8049 bc_node->get_data_reference().get_is_near_field(),
8050 ExcMessage(
8051 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
8057 Assert(
8058 hmat->property == top_hmat_node_property,
8059 ExcMessage(
8060 "A diagonal block should have the same property as that of the top level H-matrix node!"));
8061
8062 hmat->type = FullMatrixType;
8063 hmat->fullmatrix =
8064 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8065 hmat->fullmatrix->set_property(
8066 LAPACKSupport::Property::lower_triangular);
8067
8071 for (unsigned int i = 0; i < hmat->m; i++)
8072 {
8073 for (unsigned int j = 0; j < hmat->n; j++)
8074 {
8075 (*hmat->fullmatrix)(i, j) =
8076 M((*hmat->row_index_range)[0] -
8077 M_row_index_range[0] + i,
8078 (*hmat->col_index_range)[0] -
8079 M_col_index_range[0] + j);
8080 }
8081 }
8082
8083 break;
8084 }
8085 case HMatrixSupport::BlockType::lower_triangular_block: {
8093 if (bc_node->get_data_reference().get_is_near_field())
8094 {
8095 hmat->type = FullMatrixType;
8096 hmat->fullmatrix =
8097 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8098
8102 for (unsigned int i = 0; i < hmat->m; i++)
8103 {
8104 for (unsigned int j = 0; j < hmat->n; j++)
8105 {
8106 (*hmat->fullmatrix)(i, j) =
8107 M((*hmat->row_index_range)[0] -
8108 M_row_index_range[0] + i,
8109 (*hmat->col_index_range)[0] -
8110 M_col_index_range[0] + j);
8111 }
8112 }
8113 }
8114 else
8115 {
8116 hmat->type = RkMatrixType;
8117 hmat->rkmatrix =
8118 new RkMatrix<Number>(*(hmat->row_index_range),
8119 *(hmat->col_index_range),
8120 fixed_rank_k,
8121 M,
8122 M_row_index_range,
8123 M_col_index_range);
8124 }
8125
8126 break;
8127 }
8128 case HMatrixSupport::BlockType::upper_triangular_block: {
8135 if (bc_node->get_data_reference().get_is_near_field())
8136 {
8137 hmat->type = FullMatrixType;
8139 }
8140 else
8141 {
8142 hmat->type = RkMatrixType;
8143 hmat->rkmatrix =
8144 new RkMatrix<Number>(hmat->m, hmat->n, 0);
8145 }
8146
8147 break;
8148 }
8149 default: {
8150 Assert(false,
8151 ExcInvalidHMatrixBlockType(hmat->block_type));
8152 break;
8153 }
8154 }
8155
8156 break;
8157 }
8158 case HMatrixSupport::Property::upper_triangular: {
8165 switch (hmat->block_type)
8166 {
8167 case HMatrixSupport::BlockType::diagonal_block: {
8181 Assert(
8182 bc_node->get_data_reference().get_is_near_field(),
8183 ExcMessage(
8184 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
8190 Assert(
8191 hmat->property == top_hmat_node_property,
8192 ExcMessage(
8193 "A diagonal block should have the same property as that of the top level H-matrix node!"));
8194
8195 hmat->type = FullMatrixType;
8196 hmat->fullmatrix =
8197 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8198 hmat->fullmatrix->set_property(
8199 LAPACKSupport::Property::upper_triangular);
8200
8204 for (unsigned int i = 0; i < hmat->m; i++)
8205 {
8206 for (unsigned int j = 0; j < hmat->n; j++)
8207 {
8208 (*hmat->fullmatrix)(i, j) =
8209 M((*hmat->row_index_range)[0] -
8210 M_row_index_range[0] + i,
8211 (*hmat->col_index_range)[0] -
8212 M_col_index_range[0] + j);
8213 }
8214 }
8215
8216 break;
8217 }
8218 case HMatrixSupport::BlockType::upper_triangular_block: {
8226 if (bc_node->get_data_reference().get_is_near_field())
8227 {
8228 hmat->type = FullMatrixType;
8229 hmat->fullmatrix =
8230 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8231
8235 for (unsigned int i = 0; i < hmat->m; i++)
8236 {
8237 for (unsigned int j = 0; j < hmat->n; j++)
8238 {
8239 (*hmat->fullmatrix)(i, j) =
8240 M((*hmat->row_index_range)[0] -
8241 M_row_index_range[0] + i,
8242 (*hmat->col_index_range)[0] -
8243 M_col_index_range[0] + j);
8244 }
8245 }
8246 }
8247 else
8248 {
8249 hmat->type = RkMatrixType;
8250 hmat->rkmatrix =
8251 new RkMatrix<Number>(*(hmat->row_index_range),
8252 *(hmat->col_index_range),
8253 fixed_rank_k,
8254 M,
8255 M_row_index_range,
8256 M_col_index_range);
8257 }
8258
8259 break;
8260 }
8261 case HMatrixSupport::BlockType::lower_triangular_block: {
8268 if (bc_node->get_data_reference().get_is_near_field())
8269 {
8270 hmat->type = FullMatrixType;
8272 }
8273 else
8274 {
8275 hmat->type = RkMatrixType;
8276 hmat->rkmatrix =
8277 new RkMatrix<Number>(hmat->m, hmat->n, 0);
8278 }
8279
8280 break;
8281 }
8282 default: {
8283 Assert(false,
8284 ExcInvalidHMatrixBlockType(hmat->block_type));
8285 break;
8286 }
8287 }
8288
8289 break;
8290 }
8291 default: {
8292 Assert(false, ExcInvalidHMatrixProperty(top_hmat_node_property));
8293 break;
8294 }
8295 }
8296 }
8297}
8298
8299
8316template <int spacedim, typename Number = double>
8317void
8320 typename BlockClusterTree<spacedim,
8321 typename numbers::NumberTraits<Number>::real_type>::
8322 node_const_pointer_type bc_node,
8324 const std::array<types::global_dof_index, 2> &M_row_index_range,
8325 const std::array<types::global_dof_index, 2> &M_col_index_range,
8326 const HMatrixSupport::Property top_hmat_node_property =
8327 HMatrixSupport::Property::general)
8328{
8332 hmat->bc_node = const_cast<typename BlockClusterTree<
8333 spacedim,
8334 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
8335 bc_node);
8336
8340 hmat->row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
8341 &(hmat->bc_node->get_data_reference()
8342 .get_tau_node()
8343 ->get_data_reference()
8344 .get_index_range()));
8345 hmat->col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
8346 &(hmat->bc_node->get_data_reference()
8347 .get_sigma_node()
8348 ->get_data_reference()
8349 .get_index_range()));
8350
8354 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
8355 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
8356
8357 const unsigned int bc_node_child_num = bc_node->get_child_num();
8358
8359 if (bc_node_child_num > 0)
8360 {
8367
8368 for (unsigned int i = 0; i < bc_node_child_num; i++)
8369 {
8373 HMatrix<spacedim, Number> *child_hmat =
8375
8380 child_hmat->state = hmat->state;
8381
8386 switch (hmat->block_type)
8387 {
8388 case HMatrixSupport::BlockType::undefined_block: {
8393 child_hmat->block_type = hmat->block_type;
8394
8395 break;
8396 }
8397 case HMatrixSupport::BlockType::diagonal_block: {
8404 switch (i)
8405 {
8406 case 0: {
8407 child_hmat->block_type =
8408 HMatrixSupport::BlockType::diagonal_block;
8409
8410 break;
8411 }
8412 case 1: {
8413 child_hmat->block_type =
8414 HMatrixSupport::BlockType::upper_triangular_block;
8415
8416 break;
8417 }
8418 case 2: {
8419 child_hmat->block_type =
8420 HMatrixSupport::BlockType::lower_triangular_block;
8421
8422 break;
8423 }
8424 case 3: {
8425 child_hmat->block_type =
8426 HMatrixSupport::BlockType::diagonal_block;
8427
8428 break;
8429 }
8430 default: {
8431 Assert(false, ExcNotImplemented());
8432 break;
8433 }
8434 }
8435
8436 break;
8437 }
8438 case HMatrixSupport::BlockType::upper_triangular_block: {
8443 child_hmat->block_type = hmat->block_type;
8444
8445 break;
8446 }
8447 case HMatrixSupport::BlockType::lower_triangular_block: {
8452 child_hmat->block_type = hmat->block_type;
8453
8454 break;
8455 }
8456 default: {
8457 Assert(false, ExcInvalidHMatrixBlockType(hmat->block_type));
8458 break;
8459 }
8460 }
8461
8466 switch (hmat->property)
8467 {
8468 case HMatrixSupport::Property::general: {
8473 child_hmat->property = HMatrixSupport::Property::general;
8474
8475 break;
8476 }
8477 case HMatrixSupport::Property::symmetric: {
8483 if (child_hmat->block_type ==
8484 HMatrixSupport::BlockType::diagonal_block)
8485 {
8486 child_hmat->property =
8487 HMatrixSupport::Property::symmetric;
8488 }
8489 else
8490 {
8491 child_hmat->property = HMatrixSupport::Property::general;
8492 }
8493
8494 break;
8495 }
8496 case HMatrixSupport::Property::hermite_symmetric: {
8502 if (child_hmat->block_type ==
8503 HMatrixSupport::BlockType::diagonal_block)
8504 {
8505 child_hmat->property =
8506 HMatrixSupport::Property::hermite_symmetric;
8507 }
8508 else
8509 {
8510 child_hmat->property = HMatrixSupport::Property::general;
8511 }
8512
8513 break;
8514 }
8515 case HMatrixSupport::Property::upper_triangular: {
8522 if (child_hmat->block_type ==
8523 HMatrixSupport::BlockType::diagonal_block)
8524 {
8525 child_hmat->property =
8526 HMatrixSupport::Property::upper_triangular;
8527 }
8528 else
8529 {
8530 child_hmat->property = HMatrixSupport::Property::general;
8531 }
8532
8533 break;
8534 }
8535 case HMatrixSupport::Property::lower_triangular: {
8542 if (child_hmat->block_type ==
8543 HMatrixSupport::BlockType::diagonal_block)
8544 {
8545 child_hmat->property =
8546 HMatrixSupport::Property::lower_triangular;
8547 }
8548 else
8549 {
8550 child_hmat->property = HMatrixSupport::Property::general;
8551 }
8552
8553 break;
8554 }
8555 default: {
8556 Assert(false, ExcInvalidHMatrixProperty(hmat->property));
8557 break;
8558 }
8559 }
8560
8562 bc_node->get_child_pointer(i),
8563 M,
8564 M_row_index_range,
8565 M_col_index_range,
8566 top_hmat_node_property);
8567
8571 hmat->submatrices.push_back(child_hmat);
8572
8577 child_hmat->parent = hmat;
8578
8579 child_hmat->submatrix_index = i;
8580 }
8581 }
8582 else
8583 {
8593 switch (top_hmat_node_property)
8594 {
8595 case HMatrixSupport::Property::general: {
8601 if (bc_node->get_data_reference().get_is_near_field())
8602 {
8603 hmat->type = FullMatrixType;
8604 hmat->fullmatrix =
8605 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8606
8610 for (unsigned int i = 0; i < hmat->m; i++)
8611 {
8612 for (unsigned int j = 0; j < hmat->n; j++)
8613 {
8614 (*hmat->fullmatrix)(i, j) =
8615 M((*hmat->row_index_range)[0] -
8616 M_row_index_range[0] + i,
8617 (*hmat->col_index_range)[0] -
8618 M_col_index_range[0] + j);
8619 }
8620 }
8621 }
8622 else
8623 {
8624 hmat->type = RkMatrixType;
8625 hmat->rkmatrix =
8626 new RkMatrix<Number>(*(hmat->row_index_range),
8627 *(hmat->col_index_range),
8628 M,
8629 M_row_index_range,
8630 M_col_index_range);
8631 }
8632
8633 break;
8634 }
8635 case HMatrixSupport::Property::symmetric: {
8642 switch (hmat->block_type)
8643 {
8644 case HMatrixSupport::BlockType::diagonal_block: {
8658 Assert(
8659 bc_node->get_data_reference().get_is_near_field(),
8660 ExcMessage(
8661 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
8667 Assert(
8668 hmat->property == top_hmat_node_property,
8669 ExcMessage(
8670 "A diagonal block should have the same property as that of the top level H-matrix node!"));
8671
8672 hmat->type = FullMatrixType;
8673 hmat->fullmatrix =
8674 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8675 hmat->fullmatrix->set_property(
8676 LAPACKSupport::Property::symmetric);
8677
8681 for (unsigned int i = 0; i < hmat->m; i++)
8682 {
8683 for (unsigned int j = 0; j < hmat->n; j++)
8684 {
8685 (*hmat->fullmatrix)(i, j) =
8686 M((*hmat->row_index_range)[0] -
8687 M_row_index_range[0] + i,
8688 (*hmat->col_index_range)[0] -
8689 M_col_index_range[0] + j);
8690 }
8691 }
8692
8693 break;
8694 }
8695 case HMatrixSupport::BlockType::lower_triangular_block: {
8703 if (bc_node->get_data_reference().get_is_near_field())
8704 {
8705 hmat->type = FullMatrixType;
8706 hmat->fullmatrix =
8707 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8708
8712 for (unsigned int i = 0; i < hmat->m; i++)
8713 {
8714 for (unsigned int j = 0; j < hmat->n; j++)
8715 {
8716 (*hmat->fullmatrix)(i, j) =
8717 M((*hmat->row_index_range)[0] -
8718 M_row_index_range[0] + i,
8719 (*hmat->col_index_range)[0] -
8720 M_col_index_range[0] + j);
8721 }
8722 }
8723 }
8724 else
8725 {
8726 hmat->type = RkMatrixType;
8727 hmat->rkmatrix =
8728 new RkMatrix<Number>(*(hmat->row_index_range),
8729 *(hmat->col_index_range),
8730 M,
8731 M_row_index_range,
8732 M_col_index_range);
8733 }
8734
8735 break;
8736 }
8737 case HMatrixSupport::BlockType::upper_triangular_block: {
8745 if (bc_node->get_data_reference().get_is_near_field())
8746 {
8747 hmat->type = FullMatrixType;
8749 }
8750 else
8751 {
8752 hmat->type = RkMatrixType;
8753 hmat->rkmatrix =
8754 new RkMatrix<Number>(hmat->m, hmat->n, 0);
8755 }
8756
8757 break;
8758 }
8759 default: {
8760 Assert(false,
8761 ExcInvalidHMatrixBlockType(hmat->block_type));
8762 break;
8763 }
8764 }
8765
8766 break;
8767 }
8768 case HMatrixSupport::Property::hermite_symmetric: {
8775 switch (hmat->block_type)
8776 {
8777 case HMatrixSupport::BlockType::diagonal_block: {
8791 Assert(
8792 bc_node->get_data_reference().get_is_near_field(),
8793 ExcMessage(
8794 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
8800 Assert(
8801 hmat->property == top_hmat_node_property,
8802 ExcMessage(
8803 "A diagonal block should have the same property as that of the top level H-matrix node!"));
8804
8805 hmat->type = FullMatrixType;
8806 hmat->fullmatrix =
8807 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8808 hmat->fullmatrix->set_property(
8809 LAPACKSupport::Property::hermite_symmetric);
8810
8814 for (unsigned int i = 0; i < hmat->m; i++)
8815 {
8816 for (unsigned int j = 0; j < hmat->n; j++)
8817 {
8818 (*hmat->fullmatrix)(i, j) =
8819 M((*hmat->row_index_range)[0] -
8820 M_row_index_range[0] + i,
8821 (*hmat->col_index_range)[0] -
8822 M_col_index_range[0] + j);
8823 }
8824 }
8825
8826 break;
8827 }
8828 case HMatrixSupport::BlockType::lower_triangular_block: {
8836 if (bc_node->get_data_reference().get_is_near_field())
8837 {
8838 hmat->type = FullMatrixType;
8839 hmat->fullmatrix =
8840 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8841
8845 for (unsigned int i = 0; i < hmat->m; i++)
8846 {
8847 for (unsigned int j = 0; j < hmat->n; j++)
8848 {
8849 (*hmat->fullmatrix)(i, j) =
8850 M((*hmat->row_index_range)[0] -
8851 M_row_index_range[0] + i,
8852 (*hmat->col_index_range)[0] -
8853 M_col_index_range[0] + j);
8854 }
8855 }
8856 }
8857 else
8858 {
8859 hmat->type = RkMatrixType;
8860 hmat->rkmatrix =
8861 new RkMatrix<Number>(*(hmat->row_index_range),
8862 *(hmat->col_index_range),
8863 M,
8864 M_row_index_range,
8865 M_col_index_range);
8866 }
8867
8868 break;
8869 }
8870 case HMatrixSupport::BlockType::upper_triangular_block: {
8878 if (bc_node->get_data_reference().get_is_near_field())
8879 {
8880 hmat->type = FullMatrixType;
8882 }
8883 else
8884 {
8885 hmat->type = RkMatrixType;
8886 hmat->rkmatrix =
8887 new RkMatrix<Number>(hmat->m, hmat->n, 0);
8888 }
8889
8890 break;
8891 }
8892 default: {
8893 Assert(false,
8894 ExcInvalidHMatrixBlockType(hmat->block_type));
8895 break;
8896 }
8897 }
8898
8899 break;
8900 }
8901 case HMatrixSupport::Property::lower_triangular: {
8908 switch (hmat->block_type)
8909 {
8910 case HMatrixSupport::BlockType::diagonal_block: {
8924 Assert(
8925 bc_node->get_data_reference().get_is_near_field(),
8926 ExcMessage(
8927 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
8933 Assert(
8934 hmat->property == top_hmat_node_property,
8935 ExcMessage(
8936 "A diagonal block should have the same property as that of the top level H-matrix node!"));
8937
8938 hmat->type = FullMatrixType;
8939 hmat->fullmatrix =
8940 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8941 hmat->fullmatrix->set_property(
8942 LAPACKSupport::Property::lower_triangular);
8943
8947 for (unsigned int i = 0; i < hmat->m; i++)
8948 {
8949 for (unsigned int j = 0; j < hmat->n; j++)
8950 {
8951 (*hmat->fullmatrix)(i, j) =
8952 M((*hmat->row_index_range)[0] -
8953 M_row_index_range[0] + i,
8954 (*hmat->col_index_range)[0] -
8955 M_col_index_range[0] + j);
8956 }
8957 }
8958
8959 break;
8960 }
8961 case HMatrixSupport::BlockType::lower_triangular_block: {
8969 if (bc_node->get_data_reference().get_is_near_field())
8970 {
8971 hmat->type = FullMatrixType;
8972 hmat->fullmatrix =
8973 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
8974
8978 for (unsigned int i = 0; i < hmat->m; i++)
8979 {
8980 for (unsigned int j = 0; j < hmat->n; j++)
8981 {
8982 (*hmat->fullmatrix)(i, j) =
8983 M((*hmat->row_index_range)[0] -
8984 M_row_index_range[0] + i,
8985 (*hmat->col_index_range)[0] -
8986 M_col_index_range[0] + j);
8987 }
8988 }
8989 }
8990 else
8991 {
8992 hmat->type = RkMatrixType;
8993 hmat->rkmatrix =
8994 new RkMatrix<Number>(*(hmat->row_index_range),
8995 *(hmat->col_index_range),
8996 M,
8997 M_row_index_range,
8998 M_col_index_range);
8999 }
9000
9001 break;
9002 }
9003 case HMatrixSupport::BlockType::upper_triangular_block: {
9010 if (bc_node->get_data_reference().get_is_near_field())
9011 {
9012 hmat->type = FullMatrixType;
9014 }
9015 else
9016 {
9017 hmat->type = RkMatrixType;
9018 hmat->rkmatrix =
9019 new RkMatrix<Number>(hmat->m, hmat->n, 0);
9020 }
9021
9022 break;
9023 }
9024 default: {
9025 Assert(false,
9026 ExcInvalidHMatrixBlockType(hmat->block_type));
9027 break;
9028 }
9029 }
9030
9031 break;
9032 }
9033 case HMatrixSupport::Property::upper_triangular: {
9040 switch (hmat->block_type)
9041 {
9042 case HMatrixSupport::BlockType::diagonal_block: {
9056 Assert(
9057 bc_node->get_data_reference().get_is_near_field(),
9058 ExcMessage(
9059 "H-matrix node in the leaf set should belong to the near field if it is a diagonal block!"));
9065 Assert(
9066 hmat->property == top_hmat_node_property,
9067 ExcMessage(
9068 "A diagonal block should have the same property as that of the top level H-matrix node!"));
9069
9070 hmat->type = FullMatrixType;
9071 hmat->fullmatrix =
9072 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
9073 hmat->fullmatrix->set_property(
9074 LAPACKSupport::Property::upper_triangular);
9075
9079 for (unsigned int i = 0; i < hmat->m; i++)
9080 {
9081 for (unsigned int j = 0; j < hmat->n; j++)
9082 {
9083 (*hmat->fullmatrix)(i, j) =
9084 M((*hmat->row_index_range)[0] -
9085 M_row_index_range[0] + i,
9086 (*hmat->col_index_range)[0] -
9087 M_col_index_range[0] + j);
9088 }
9089 }
9090
9091 break;
9092 }
9093 case HMatrixSupport::BlockType::upper_triangular_block: {
9101 if (bc_node->get_data_reference().get_is_near_field())
9102 {
9103 hmat->type = FullMatrixType;
9104 hmat->fullmatrix =
9105 new LAPACKFullMatrixExt<Number>(hmat->m, hmat->n);
9106
9110 for (unsigned int i = 0; i < hmat->m; i++)
9111 {
9112 for (unsigned int j = 0; j < hmat->n; j++)
9113 {
9114 (*hmat->fullmatrix)(i, j) =
9115 M((*hmat->row_index_range)[0] -
9116 M_row_index_range[0] + i,
9117 (*hmat->col_index_range)[0] -
9118 M_col_index_range[0] + j);
9119 }
9120 }
9121 }
9122 else
9123 {
9124 hmat->type = RkMatrixType;
9125 hmat->rkmatrix =
9126 new RkMatrix<Number>(*(hmat->row_index_range),
9127 *(hmat->col_index_range),
9128 M,
9129 M_row_index_range,
9130 M_col_index_range);
9131 }
9132
9133 break;
9134 }
9135 case HMatrixSupport::BlockType::lower_triangular_block: {
9142 if (bc_node->get_data_reference().get_is_near_field())
9143 {
9144 hmat->type = FullMatrixType;
9146 }
9147 else
9148 {
9149 hmat->type = RkMatrixType;
9150 hmat->rkmatrix =
9151 new RkMatrix<Number>(hmat->m, hmat->n, 0);
9152 }
9153
9154 break;
9155 }
9156 default: {
9157 Assert(false,
9158 ExcInvalidHMatrixBlockType(hmat->block_type));
9159 break;
9160 }
9161 }
9162
9163 break;
9164 }
9165 default: {
9166 Assert(false, ExcInvalidHMatrixProperty(top_hmat_node_property));
9167 break;
9168 }
9169 }
9170 }
9171}
9172
9173
9187template <int spacedim, typename Number = double>
9188void
9191 typename BlockClusterTree<spacedim,
9192 typename numbers::NumberTraits<Number>::real_type>::
9193 node_const_pointer_type bc_node,
9195{
9200 hmat->bc_node = const_cast<typename BlockClusterTree<
9201 spacedim,
9202 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type>(
9203 bc_node);
9204
9209 hmat->row_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
9210 &(hmat->bc_node->get_data_reference()
9211 .get_tau_node()
9212 ->get_data_reference()
9213 .get_index_range()));
9214 hmat->col_index_range = const_cast<std::array<types::global_dof_index, 2> *>(
9215 &(hmat->bc_node->get_data_reference()
9216 .get_sigma_node()
9217 ->get_data_reference()
9218 .get_index_range()));
9219
9223 hmat->m = (*hmat->row_index_range)[1] - (*hmat->row_index_range)[0];
9224 hmat->n = (*hmat->col_index_range)[1] - (*hmat->col_index_range)[0];
9225
9226 const unsigned int bc_node_child_num = bc_node->get_child_num();
9227
9228 if (bc_node_child_num > 0)
9229 {
9235
9239 for (unsigned int i = 0; i < bc_node_child_num; i++)
9240 {
9244 HMatrix<spacedim, Number> *child_hmat =
9246
9251 child_hmat->state = hmat->state;
9252
9257 switch (hmat->block_type)
9258 {
9259 case HMatrixSupport::BlockType::undefined_block: {
9264 child_hmat->block_type = hmat->block_type;
9265
9266 break;
9267 }
9268 case HMatrixSupport::BlockType::diagonal_block: {
9275 switch (i)
9276 {
9277 case 0: {
9278 child_hmat->block_type =
9279 HMatrixSupport::BlockType::diagonal_block;
9280
9281 break;
9282 }
9283 case 1: {
9284 child_hmat->block_type =
9285 HMatrixSupport::BlockType::upper_triangular_block;
9286
9287 break;
9288 }
9289 case 2: {
9290 child_hmat->block_type =
9291 HMatrixSupport::BlockType::lower_triangular_block;
9292
9293 break;
9294 }
9295 case 3: {
9296 child_hmat->block_type =
9297 HMatrixSupport::BlockType::diagonal_block;
9298
9299 break;
9300 }
9301 default: {
9302 Assert(false, ExcNotImplemented());
9303 break;
9304 }
9305 }
9306
9307 break;
9308 }
9309 case HMatrixSupport::BlockType::upper_triangular_block: {
9314 child_hmat->block_type = hmat->block_type;
9315
9316 break;
9317 }
9318 case HMatrixSupport::BlockType::lower_triangular_block: {
9323 child_hmat->block_type = hmat->block_type;
9324
9325 break;
9326 }
9327 default: {
9328 Assert(false, ExcInvalidHMatrixBlockType(hmat->block_type));
9329 break;
9330 }
9331 }
9332
9337 switch (hmat->property)
9338 {
9339 case HMatrixSupport::Property::general: {
9344 child_hmat->property = HMatrixSupport::Property::general;
9345
9346 break;
9347 }
9348 case HMatrixSupport::Property::symmetric: {
9354 if (child_hmat->block_type ==
9355 HMatrixSupport::BlockType::diagonal_block)
9356 {
9357 child_hmat->property =
9358 HMatrixSupport::Property::symmetric;
9359 }
9360 else
9361 {
9362 child_hmat->property = HMatrixSupport::Property::general;
9363 }
9364
9365 break;
9366 }
9367 case HMatrixSupport::Property::hermite_symmetric: {
9373 if (child_hmat->block_type ==
9374 HMatrixSupport::BlockType::diagonal_block)
9375 {
9376 child_hmat->property =
9377 HMatrixSupport::Property::hermite_symmetric;
9378 }
9379 else
9380 {
9381 child_hmat->property = HMatrixSupport::Property::general;
9382 }
9383
9384 break;
9385 }
9386 case HMatrixSupport::Property::upper_triangular: {
9393 if (child_hmat->block_type ==
9394 HMatrixSupport::BlockType::diagonal_block)
9395 {
9396 child_hmat->property =
9397 HMatrixSupport::Property::upper_triangular;
9398 }
9399 else
9400 {
9401 child_hmat->property = HMatrixSupport::Property::general;
9402 }
9403
9404 break;
9405 }
9406 case HMatrixSupport::Property::lower_triangular: {
9413 if (child_hmat->block_type ==
9414 HMatrixSupport::BlockType::diagonal_block)
9415 {
9416 child_hmat->property =
9417 HMatrixSupport::Property::lower_triangular;
9418 }
9419 else
9420 {
9421 child_hmat->property = HMatrixSupport::Property::general;
9422 }
9423
9424 break;
9425 }
9426 default: {
9427 Assert(false, ExcInvalidHMatrixProperty(hmat->property));
9428 break;
9429 }
9430 }
9431
9433 bc_node->get_child_pointer(i),
9434 std::move(H));
9435
9439 hmat->submatrices.push_back(child_hmat);
9440
9445 child_hmat->parent = hmat;
9446
9447 child_hmat->submatrix_index = i;
9448 }
9449 }
9450 else
9451 {
9456 HMatrix<spacedim, Number> *matched_source_hmat = *(
9457 H.find_block_cluster_in_leaf_set(hmat->bc_node->get_data_reference()));
9462 (*hmat) = std::move(*matched_source_hmat);
9463 }
9464}
9465
9466
9481template <int spacedim, typename Number>
9482void
9484 HMatrix<spacedim, Number> *starting_hmat,
9485 HMatrix<spacedim, Number> *current_hmat)
9486{
9495 Assert((starting_hmat->type == FullMatrixType) ||
9496 (starting_hmat->type == RkMatrixType),
9497 ExcInvalidHMatrixType(starting_hmat->type));
9498
9506 const unsigned int bc_node_child_num = current_hmat->bc_node->get_child_num();
9507
9508 if (bc_node_child_num > 0)
9509 {
9525 if (current_hmat != starting_hmat)
9526 {
9527 current_hmat->type = HierarchicalMatrixType;
9528 }
9529
9530 for (unsigned int i = 0; i < bc_node_child_num; i++)
9531 {
9537 HMatrix<spacedim, Number> *child_hmat =
9539
9544 child_hmat->state = current_hmat->state;
9545
9550 switch (current_hmat->block_type)
9551 {
9552 case HMatrixSupport::BlockType::undefined_block: {
9557 child_hmat->block_type = current_hmat->block_type;
9558
9559 break;
9560 }
9561 case HMatrixSupport::BlockType::diagonal_block: {
9568 switch (i)
9569 {
9570 case 0: {
9571 child_hmat->block_type =
9572 HMatrixSupport::BlockType::diagonal_block;
9573
9574 break;
9575 }
9576 case 1: {
9577 child_hmat->block_type =
9578 HMatrixSupport::BlockType::upper_triangular_block;
9579
9580 break;
9581 }
9582 case 2: {
9583 child_hmat->block_type =
9584 HMatrixSupport::BlockType::lower_triangular_block;
9585
9586 break;
9587 }
9588 case 3: {
9589 child_hmat->block_type =
9590 HMatrixSupport::BlockType::diagonal_block;
9591
9592 break;
9593 }
9594 default: {
9595 Assert(false, ExcNotImplemented());
9596 break;
9597 }
9598 }
9599
9600 break;
9601 }
9602 case HMatrixSupport::BlockType::upper_triangular_block: {
9607 child_hmat->block_type = current_hmat->block_type;
9608
9609 break;
9610 }
9611 case HMatrixSupport::BlockType::lower_triangular_block: {
9616 child_hmat->block_type = current_hmat->block_type;
9617
9618 break;
9619 }
9620 default: {
9621 Assert(false,
9622 ExcMessage("Invalid H-matrix block type: " +
9623 std::to_string(current_hmat->block_type)));
9624 break;
9625 }
9626 }
9627
9632 switch (current_hmat->property)
9633 {
9634 case HMatrixSupport::Property::general: {
9639 child_hmat->property = HMatrixSupport::Property::general;
9640
9641 break;
9642 }
9643 case HMatrixSupport::Property::symmetric: {
9649 if (child_hmat->block_type ==
9650 HMatrixSupport::BlockType::diagonal_block)
9651 {
9652 child_hmat->property =
9653 HMatrixSupport::Property::symmetric;
9654 }
9655 else
9656 {
9657 child_hmat->property = HMatrixSupport::Property::general;
9658 }
9659
9660 break;
9661 }
9662 case HMatrixSupport::Property::hermite_symmetric: {
9668 if (child_hmat->block_type ==
9669 HMatrixSupport::BlockType::diagonal_block)
9670 {
9671 child_hmat->property =
9672 HMatrixSupport::Property::hermite_symmetric;
9673 }
9674 else
9675 {
9676 child_hmat->property = HMatrixSupport::Property::general;
9677 }
9678
9679 break;
9680 }
9681 case HMatrixSupport::Property::upper_triangular: {
9688 if (child_hmat->block_type ==
9689 HMatrixSupport::BlockType::diagonal_block)
9690 {
9691 child_hmat->property =
9692 HMatrixSupport::Property::upper_triangular;
9693 }
9694 else
9695 {
9696 child_hmat->property = HMatrixSupport::Property::general;
9697 }
9698
9699 break;
9700 }
9701 case HMatrixSupport::Property::lower_triangular: {
9708 if (child_hmat->block_type ==
9709 HMatrixSupport::BlockType::diagonal_block)
9710 {
9711 child_hmat->property =
9712 HMatrixSupport::Property::lower_triangular;
9713 }
9714 else
9715 {
9716 child_hmat->property = HMatrixSupport::Property::general;
9717 }
9718
9719 break;
9720 }
9721 default: {
9722 Assert(false,
9723 ExcMessage("Invalid H-matrix property: " +
9724 std::to_string(current_hmat->property)));
9725 break;
9726 }
9727 }
9728
9729 current_hmat->submatrices.push_back(child_hmat);
9730
9735 child_hmat->bc_node = const_cast<
9736 typename BlockClusterTree<spacedim,
9737 typename numbers::NumberTraits<
9738 Number>::real_type>::node_pointer_type>(
9739 current_hmat->bc_node->get_child_pointer(i));
9740
9745 child_hmat->row_index_range =
9746 const_cast<std::array<types::global_dof_index, 2> *>(
9747 &(child_hmat->bc_node->get_data_reference()
9748 .get_tau_node()
9749 ->get_data_reference()
9750 .get_index_range()));
9751 child_hmat->col_index_range =
9752 const_cast<std::array<types::global_dof_index, 2> *>(
9753 &(child_hmat->bc_node->get_data_reference()
9754 .get_sigma_node()
9755 ->get_data_reference()
9756 .get_index_range()));
9757
9762 child_hmat->m = (*child_hmat->row_index_range)[1] -
9763 (*child_hmat->row_index_range)[0];
9764 child_hmat->n = (*child_hmat->col_index_range)[1] -
9765 (*child_hmat->col_index_range)[0];
9766
9771 child_hmat->parent = current_hmat;
9772
9773 child_hmat->submatrix_index = i;
9774
9778 RefineHMatrixWrtExtendedBlockClusterTree(starting_hmat, child_hmat);
9779 }
9780 }
9781 else
9782 {
9787 if (current_hmat == starting_hmat)
9788 {
9794 }
9795 else
9796 {
9808 if (current_hmat->bc_node->get_data_reference().get_is_near_field())
9809 {
9810 current_hmat->type = FullMatrixType;
9811
9817 switch (starting_hmat->type)
9818 {
9819 case FullMatrixType: {
9823 current_hmat->fullmatrix =
9825 *(current_hmat->row_index_range),
9826 *(current_hmat->col_index_range),
9827 *(starting_hmat->fullmatrix),
9828 *starting_hmat->row_index_range,
9829 *starting_hmat->col_index_range);
9830
9831 break;
9832 }
9833 case RkMatrixType: {
9837 current_hmat->fullmatrix =
9839 starting_hmat->rkmatrix->restrictToFullMatrix(
9840 *starting_hmat->row_index_range,
9841 *starting_hmat->col_index_range,
9842 *(current_hmat->fullmatrix),
9843 *(current_hmat->row_index_range),
9844 *(current_hmat->col_index_range));
9845
9846 break;
9847 }
9848 default: {
9849 Assert(false, ExcInvalidHMatrixType(starting_hmat->type));
9850
9851 break;
9852 }
9853 }
9854
9864 if (current_hmat->block_type ==
9865 HMatrixSupport::BlockType::diagonal_block)
9866 {
9867 switch (current_hmat->property)
9868 {
9869 case HMatrixSupport::Property::general: {
9870 current_hmat->fullmatrix->set_property(
9871 LAPACKSupport::Property::general);
9872
9873 break;
9874 }
9875 case HMatrixSupport::Property::symmetric: {
9876 current_hmat->fullmatrix->set_property(
9877 LAPACKSupport::Property::symmetric);
9878
9879 break;
9880 }
9881 case HMatrixSupport::Property::hermite_symmetric: {
9882 current_hmat->fullmatrix->set_property(
9883 LAPACKSupport::Property::hermite_symmetric);
9884
9885 break;
9886 }
9887 case HMatrixSupport::Property::upper_triangular: {
9888 current_hmat->fullmatrix->set_property(
9889 LAPACKSupport::Property::upper_triangular);
9890
9891 break;
9892 }
9893 case HMatrixSupport::Property::lower_triangular: {
9894 current_hmat->fullmatrix->set_property(
9895 LAPACKSupport::Property::lower_triangular);
9896
9897 break;
9898 }
9899 default: {
9900 Assert(false,
9901 ExcMessage(
9902 "Invalid H-matrix property: " +
9903 std::to_string(current_hmat->property)));
9904 break;
9905 }
9906 }
9907 }
9908 }
9909 else
9910 {
9911 current_hmat->type = RkMatrixType;
9912
9917 switch (starting_hmat->type)
9918 {
9919 case FullMatrixType: {
9923 current_hmat->rkmatrix =
9924 new RkMatrix<Number>(*(current_hmat->row_index_range),
9925 *(current_hmat->col_index_range),
9926 *(starting_hmat->fullmatrix),
9927 *starting_hmat->row_index_range,
9928 *starting_hmat->col_index_range);
9929
9930 break;
9931 }
9932 case RkMatrixType: {
9936 current_hmat->rkmatrix =
9937 new RkMatrix<Number>(*(current_hmat->row_index_range),
9938 *(current_hmat->col_index_range),
9939 *(starting_hmat->rkmatrix),
9940 *starting_hmat->row_index_range,
9941 *starting_hmat->col_index_range);
9942
9943 break;
9944 }
9945 default: {
9946 Assert(false, ExcInvalidHMatrixType(starting_hmat->type));
9947
9948 break;
9949 }
9950 }
9951 }
9952 }
9953 }
9954
9959}
9960
9961
10015template <int spacedim, typename Number = double>
10016void
10018 HMatrix<spacedim, Number> *hmat_block,
10019 const unsigned int fixed_rank_k,
10020 const HMatrix<spacedim, Number> *hmat_root_block = nullptr,
10021 size_t *calling_counter = nullptr,
10022 const std::string &output_file_base_name = std::string("hmat-bct"))
10023{
10030
10031 Assert(hmat_block->type != UndefinedMatrixType,
10032 ExcInvalidHMatrixType(hmat_block->type));
10033
10034 if (hmat_block->bc_node->is_leaf())
10035 {
10040 if (hmat_block->bc_node->get_data_reference().get_is_near_field())
10041 {
10049 Assert(hmat_block->type == FullMatrixType,
10050 ExcInvalidHMatrixType(hmat_block->type));
10051 }
10052 else
10053 {
10060 Assert(hmat_block->type == RkMatrixType,
10061 ExcInvalidHMatrixType(hmat_block->type));
10062
10063 hmat_block->rkmatrix->truncate_to_rank(fixed_rank_k);
10064 }
10065 }
10066 else
10067 {
10073 for (auto submatrix : hmat_block->submatrices)
10074 {
10076 fixed_rank_k,
10077 hmat_root_block,
10078 calling_counter,
10079 output_file_base_name);
10080 }
10081
10082 if (hmat_block->bc_node->get_data_reference().get_is_near_field())
10083 {
10136 for (const HMatrix<spacedim, Number> *submatrix :
10137 hmat_block->submatrices)
10138 {
10139 Assert(submatrix->type == FullMatrixType,
10140 ExcInvalidHMatrixType(submatrix->type));
10141 }
10142
10143 LAPACKFullMatrixExt<Number> *fullmatrix;
10144
10145 switch (hmat_block->bc_node->get_split_mode())
10146 {
10147 case CrossSplitMode: {
10148 AssertDimension(hmat_block->submatrices.size(), 4);
10149
10150 fullmatrix = new LAPACKFullMatrixExt<Number>(
10151 *(hmat_block->submatrices[0]->fullmatrix),
10152 *(hmat_block->submatrices[1]->fullmatrix),
10153 *(hmat_block->submatrices[2]->fullmatrix),
10154 *(hmat_block->submatrices[3]->fullmatrix));
10155
10156 break;
10157 }
10158 case HorizontalSplitMode: {
10159 AssertDimension(hmat_block->submatrices.size(), 2);
10160
10161 fullmatrix = new LAPACKFullMatrixExt<Number>(
10162 *(hmat_block->submatrices[0]->fullmatrix),
10163 *(hmat_block->submatrices[1]->fullmatrix),
10164 true);
10165
10166 break;
10167 }
10168 case VerticalSplitMode: {
10169 AssertDimension(hmat_block->submatrices.size(), 2);
10170
10171 fullmatrix = new LAPACKFullMatrixExt<Number>(
10172 *(hmat_block->submatrices[0]->fullmatrix),
10173 *(hmat_block->submatrices[1]->fullmatrix),
10174 false);
10175
10176 break;
10177 }
10178 default: {
10179 Assert(
10180 false,
10181 ExcMessage(
10182 std::string("Invalid block cluster splitting mode: ") +
10183 std::to_string(hmat_block->bc_node->get_split_mode())));
10184 break;
10185 }
10186 }
10187
10188 for (HMatrix<spacedim, Number> *submatrix : hmat_block->submatrices)
10189 {
10190 if (submatrix != nullptr)
10191 {
10192 delete submatrix;
10193 }
10194 }
10195 hmat_block->submatrices.clear();
10196
10197 hmat_block->fullmatrix = fullmatrix;
10198 hmat_block->type = FullMatrixType;
10199 }
10200 else
10201 {
10208 RkMatrix<Number> *rkmatrix;
10209
10210 switch (hmat_block->bc_node->get_split_mode())
10211 {
10212 case CrossSplitMode: {
10213 AssertDimension(hmat_block->submatrices.size(), 4);
10214
10215 if (hmat_block->submatrices[0]->type == RkMatrixType &&
10216 hmat_block->submatrices[1]->type == RkMatrixType &&
10217 hmat_block->submatrices[2]->type == RkMatrixType &&
10218 hmat_block->submatrices[3]->type == RkMatrixType)
10219 {
10225 rkmatrix = new RkMatrix<Number>(
10226 fixed_rank_k,
10227 *(hmat_block->submatrices[0]->rkmatrix),
10228 *(hmat_block->submatrices[1]->rkmatrix),
10229 *(hmat_block->submatrices[2]->rkmatrix),
10230 *(hmat_block->submatrices[3]->rkmatrix));
10231 }
10232 else if (hmat_block->submatrices[0]->type == FullMatrixType &&
10233 hmat_block->submatrices[1]->type == FullMatrixType &&
10234 hmat_block->submatrices[2]->type == FullMatrixType &&
10235 hmat_block->submatrices[3]->type == FullMatrixType)
10236 {
10243 RkMatrix<Number> rkmatrix11(
10244 fixed_rank_k,
10245 *(hmat_block->submatrices[0]->fullmatrix));
10246 RkMatrix<Number> rkmatrix12(
10247 fixed_rank_k,
10248 *(hmat_block->submatrices[1]->fullmatrix));
10249 RkMatrix<Number> rkmatrix21(
10250 fixed_rank_k,
10251 *(hmat_block->submatrices[2]->fullmatrix));
10252 RkMatrix<Number> rkmatrix22(
10253 fixed_rank_k,
10254 *(hmat_block->submatrices[3]->fullmatrix));
10255
10256 rkmatrix = new RkMatrix<Number>(fixed_rank_k,
10257 rkmatrix11,
10258 rkmatrix12,
10259 rkmatrix21,
10260 rkmatrix22);
10261 }
10262 else
10263 {
10267 Assert(false, ExcInternalError());
10268 }
10269
10270 break;
10271 }
10272 case HorizontalSplitMode: {
10273 AssertDimension(hmat_block->submatrices.size(), 2);
10274
10275 if (hmat_block->submatrices[0]->type == RkMatrixType &&
10276 hmat_block->submatrices[1]->type == RkMatrixType)
10277 {
10283 rkmatrix = new RkMatrix<Number>(
10284 fixed_rank_k,
10285 *(hmat_block->submatrices[0]->rkmatrix),
10286 *(hmat_block->submatrices[1]->rkmatrix),
10287 true);
10288 }
10289 else if (hmat_block->submatrices[0]->type == FullMatrixType &&
10290 hmat_block->submatrices[1]->type == FullMatrixType)
10291 {
10298 RkMatrix<Number> rkmatrix1(
10299 fixed_rank_k,
10300 *(hmat_block->submatrices[0]->fullmatrix));
10301 RkMatrix<Number> rkmatrix2(
10302 fixed_rank_k,
10303 *(hmat_block->submatrices[1]->fullmatrix));
10304
10305 rkmatrix = new RkMatrix<Number>(fixed_rank_k,
10306 rkmatrix1,
10307 rkmatrix2,
10308 true);
10309 }
10310 else
10311 {
10315 Assert(false, ExcInternalError());
10316 }
10317
10318 break;
10319 }
10320 case VerticalSplitMode: {
10321 AssertDimension(hmat_block->submatrices.size(), 2);
10322
10323 if (hmat_block->submatrices[0]->type == RkMatrixType &&
10324 hmat_block->submatrices[1]->type == RkMatrixType)
10325 {
10331 rkmatrix = new RkMatrix<Number>(
10332 fixed_rank_k,
10333 *(hmat_block->submatrices[0]->rkmatrix),
10334 *(hmat_block->submatrices[1]->rkmatrix),
10335 false);
10336 }
10337 else if (hmat_block->submatrices[0]->type == FullMatrixType &&
10338 hmat_block->submatrices[1]->type == FullMatrixType)
10339 {
10346 RkMatrix<Number> rkmatrix1(
10347 fixed_rank_k,
10348 *(hmat_block->submatrices[0]->fullmatrix));
10349 RkMatrix<Number> rkmatrix2(
10350 fixed_rank_k,
10351 *(hmat_block->submatrices[1]->fullmatrix));
10352
10353 rkmatrix = new RkMatrix<Number>(fixed_rank_k,
10354 rkmatrix1,
10355 rkmatrix2,
10356 false);
10357 }
10358 else
10359 {
10363 Assert(false, ExcInternalError());
10364 }
10365
10366 break;
10367 }
10368 default: {
10369 Assert(
10370 false,
10371 ExcMessage(
10372 std::string("Invalid block cluster splitting mode: ") +
10373 std::to_string(hmat_block->bc_node->get_split_mode())));
10374 break;
10375 }
10376 }
10377
10378 for (HMatrix<spacedim, Number> *submatrix : hmat_block->submatrices)
10379 {
10380 if (submatrix != nullptr)
10381 {
10382 delete submatrix;
10383 }
10384 }
10385 hmat_block->submatrices.clear();
10386
10387 hmat_block->rkmatrix = rkmatrix;
10388 hmat_block->type = RkMatrixType;
10389 }
10390
10396 if (hmat_root_block != nullptr && calling_counter != nullptr)
10397 {
10398 std::ofstream output_stream(
10399 output_file_base_name + std::to_string(*calling_counter) + ".dat");
10400 hmat_root_block->write_leaf_set(output_stream);
10401 output_stream.close();
10402
10403 (*calling_counter) = (*calling_counter) + 1;
10404 }
10405 }
10410}
10411
10412
10442template <int spacedim, typename Number = double>
10443void
10445 const RkMatrix<Number> &M2,
10447{
10448 AssertDimension(M1.n, M2.m);
10449
10450 if (M2.rank > 0 && M2.formal_rank > 0)
10451 {
10457 Vector<Number> col_vect_in_A(M2.A.m());
10458 Vector<Number> result_vect(M1.m);
10459
10464 M.reinit(M1.m, M2.n, M2.formal_rank);
10465 M.B = M2.B;
10466
10471 for (size_t j = 0; j < M2.formal_rank; j++)
10472 {
10473 M2.A.get_column(j, col_vect_in_A);
10474 result_vect = Number(0.);
10475 M1.vmult(result_vect, col_vect_in_A, M1, M1.get_property());
10476
10480 M.A.fill_col(j, result_vect);
10481 }
10482 }
10483 else
10484 {
10485 M.reinit(M1.m, M2.n, 0);
10486 }
10487}
10488
10489
10516template <int spacedim, typename Number = double>
10517void
10518h_rk_mmult(const Number alpha,
10520 const RkMatrix<Number> &M2,
10522{
10523 AssertDimension(M1.n, M2.m);
10524
10525 if (M2.rank > 0 && M2.formal_rank > 0)
10526 {
10532 Vector<Number> col_vect_in_A(M2.A.m());
10533 Vector<Number> result_vect(M1.m);
10534
10539 M.reinit(M1.m, M2.n, M2.formal_rank);
10540 M.B = M2.B;
10541
10546 for (size_t j = 0; j < M2.formal_rank; j++)
10547 {
10548 M2.A.get_column(j, col_vect_in_A);
10553 result_vect = Number(0.);
10554 M1.vmult(result_vect, alpha, col_vect_in_A, M1, M1.get_property());
10555
10559 M.A.fill_col(j, result_vect);
10560 }
10561 }
10562 else
10563 {
10564 M.reinit(M1.m, M2.n, 0);
10565 }
10566}
10567
10568
10599template <int spacedim, typename Number = double>
10600void
10602 const RkMatrix<Number> &M2,
10604{
10605 AssertDimension(M1.n, M2.n);
10606
10607 if (M2.rank > 0 && M2.formal_rank > 0)
10608 {
10614 Vector<Number> col_vect_in_B(M2.B.m());
10615 Vector<Number> result_vect(M1.m);
10616
10621 M.reinit(M1.m, M2.m, M2.formal_rank);
10622 M.B = M2.A;
10623
10628 for (size_t j = 0; j < M2.formal_rank; j++)
10629 {
10630 M2.B.get_column(j, col_vect_in_B);
10631 result_vect = Number(0.);
10632 M1.vmult(result_vect, col_vect_in_B, M1, M1.get_property());
10633
10637 M.A.fill_col(j, result_vect);
10638 }
10639 }
10640 else
10641 {
10642 M.reinit(M1.m, M2.m, 0);
10643 }
10644}
10645
10646
10670template <int spacedim, typename Number = double>
10671void
10672h_rk_mTmult(const Number alpha,
10674 const RkMatrix<Number> &M2,
10676{
10677 AssertDimension(M1.n, M2.n);
10678
10679 if (M2.rank > 0 && M2.formal_rank > 0)
10680 {
10686 Vector<Number> col_vect_in_B(M2.B.m());
10687 Vector<Number> result_vect(M1.m);
10688
10693 M.reinit(M1.m, M2.m, M2.formal_rank);
10694 M.B = M2.A;
10695
10700 for (size_t j = 0; j < M2.formal_rank; j++)
10701 {
10702 M2.B.get_column(j, col_vect_in_B);
10703 result_vect = Number(0.);
10704 M1.vmult(result_vect, alpha, col_vect_in_B, M1, M1.get_property());
10705
10709 M.A.fill_col(j, result_vect);
10710 }
10711 }
10712 else
10713 {
10714 M.reinit(M1.m, M2.m, 0);
10715 }
10716}
10717
10718
10749template <int spacedim, typename Number = double>
10750void
10752 const RkMatrix<Number> &M2,
10754{
10755 AssertDimension(M1.m, M2.m);
10756
10757 if (M2.rank > 0 && M2.formal_rank > 0)
10758 {
10764 Vector<Number> col_vect_in_A(M2.A.m());
10765 Vector<Number> result_vect(M1.n);
10766
10771 M.reinit(M1.n, M2.n, M2.formal_rank);
10772 M.B = M2.B;
10773
10778 for (size_t j = 0; j < M2.formal_rank; j++)
10779 {
10780 M2.A.get_column(j, col_vect_in_A);
10781 result_vect = Number(0.);
10782 M1.Tvmult(result_vect, col_vect_in_A, M1, M1.get_property());
10783
10787 M.A.fill_col(j, result_vect);
10788 }
10789 }
10790 else
10791 {
10792 M.reinit(M1.n, M2.n, 0);
10793 }
10794}
10795
10796
10830template <int spacedim, typename Number = double>
10831void
10832h_rk_Tmmult(const Number alpha,
10834 const RkMatrix<Number> &M2,
10836{
10837 AssertDimension(M1.m, M2.m);
10838
10839 if (M2.rank > 0 && M2.formal_rank > 0)
10840 {
10846 Vector<Number> col_vect_in_A(M2.A.m());
10847 Vector<Number> result_vect(M1.n);
10848
10853 M.reinit(M1.n, M2.n, M2.formal_rank);
10854 M.B = M2.B;
10855
10860 for (size_t j = 0; j < M2.formal_rank; j++)
10861 {
10862 M2.A.get_column(j, col_vect_in_A);
10863 result_vect = Number(0.);
10864 M1.Tvmult(result_vect, alpha, col_vect_in_A, M1, M1.get_property());
10865
10869 M.A.fill_col(j, result_vect);
10870 }
10871 }
10872 else
10873 {
10874 M.reinit(M1.n, M2.n, 0);
10875 }
10876}
10877
10878
10888template <int spacedim, typename Number = double>
10889void
10891 const HMatrix<spacedim, Number> *M2,
10893 bool is_M1M2_last_in_M_Sigma_P = true)
10894{
10895 Assert(M2->type == RkMatrixType, ExcInvalidHMatrixType(M2->type));
10896 Assert(M2->rkmatrix, ExcInternalError());
10897 // Assert(*(M1->col_index_range) == *(M2->row_index_range),
10898 // ExcMessage("Incompatible index sets during matrix
10899 // multiplication"));
10900 AssertDimension(M1->n, M2->m);
10901
10902 // DEBUG
10903 // print_h_h_submatrix_mmult_accessor(std::cout, "M1", *M1, "M2", *M2);
10904
10905 if (is_M1M2_last_in_M_Sigma_P)
10906 {
10907 M->Sigma_P.pop_back();
10908 }
10909 else
10910 {
10912 }
10913
10914 RkMatrix<Number> *M_rk = new RkMatrix<Number>();
10915 h_rk_mmult(*M1, *(M2->rkmatrix), *M_rk);
10916 M->Sigma_R.push_back(M_rk);
10917
10918 // // DEBUG
10919 // LAPACKFullMatrixExt<Number> M_rk_to_full;
10920 // M_rk->convertToFullMatrix(M_rk_to_full);
10921 // M_rk_to_full.print_formatted(std::cout, 8, false, 16, "0");
10922
10923 AssertDimension(M->Sigma_F.size(), 0);
10924 M->type = RkMatrixType;
10925}
10926
10927
10957template <int spacedim, typename Number = double>
10958void
10962{
10963 AssertDimension(M1.n, M2.m);
10964
10965 if (M1.rank > 0 && M1.formal_rank > 0)
10966 {
10972 Vector<Number> col_vect_in_B(M1.B.m());
10973 Vector<Number> result_vect(M2.n);
10974
10979 M.reinit(M1.m, M2.n, M1.formal_rank);
10980 M.A = M1.A;
10981
10986 for (size_t j = 0; j < M.formal_rank; j++)
10987 {
10988 M1.B.get_column(j, col_vect_in_B);
10989 result_vect = Number(0.);
10990 M2.Tvmult(result_vect, col_vect_in_B, M2, M2.get_property());
10991
10995 M.B.fill_col(j, result_vect);
10996 }
10997 }
10998 else
10999 {
11000 M.reinit(M1.m, M2.n, 0);
11001 }
11002}
11003
11004
11036template <int spacedim, typename Number = double>
11037void
11038rk_h_mmult(const Number alpha,
11039 const RkMatrix<Number> &M1,
11042{
11043 AssertDimension(M1.n, M2.m);
11044
11045 if (M1.rank > 0 && M1.formal_rank > 0)
11046 {
11052 Vector<Number> col_vect_in_B(M1.B.m());
11053 Vector<Number> result_vect(M2.n);
11054
11059 M.reinit(M1.m, M2.n, M1.formal_rank);
11060 M.A = M1.A;
11061
11066 for (size_t j = 0; j < M.formal_rank; j++)
11067 {
11068 M1.B.get_column(j, col_vect_in_B);
11073 result_vect = Number(0.);
11074 M2.Tvmult(result_vect, alpha, col_vect_in_B, M2, M2.get_property());
11075
11079 M.B.fill_col(j, result_vect);
11080 }
11081 }
11082 else
11083 {
11084 M.reinit(M1.m, M2.n, 0);
11085 }
11086}
11087
11088
11117template <int spacedim, typename Number = double>
11118void
11122{
11123 AssertDimension(M1.n, M2.n);
11124
11125 if (M1.rank > 0 && M1.formal_rank > 0)
11126 {
11132 Vector<Number> col_vect_in_B(M1.B.m());
11133 Vector<Number> result_vect(M2.m);
11134
11139 M.reinit(M1.m, M2.m, M1.formal_rank);
11140 M.A = M1.A;
11141
11146 for (size_t j = 0; j < M.formal_rank; j++)
11147 {
11148 M1.B.get_column(j, col_vect_in_B);
11149 result_vect = Number(0.);
11150 M2.vmult(result_vect, col_vect_in_B, M2, M2.get_property());
11151
11155 M.B.fill_col(j, result_vect);
11156 }
11157 }
11158 else
11159 {
11160 M.reinit(M1.m, M2.m, 0);
11161 }
11162}
11163
11164
11192template <int spacedim, typename Number = double>
11193void
11194rk_h_mTmult(const Number alpha,
11195 const RkMatrix<Number> &M1,
11198{
11199 AssertDimension(M1.n, M2.n);
11200
11201 if (M1.rank > 0 && M1.formal_rank > 0)
11202 {
11208 Vector<Number> col_vect_in_B(M1.B.m());
11209 Vector<Number> result_vect(M2.m);
11210
11215 M.reinit(M1.m, M2.m, M1.formal_rank);
11216 M.A = M1.A;
11217
11222 for (size_t j = 0; j < M.formal_rank; j++)
11223 {
11224 M1.B.get_column(j, col_vect_in_B);
11225 result_vect = Number(0.);
11226 M2.vmult(result_vect, alpha, col_vect_in_B, M2, M2.get_property());
11227
11231 M.B.fill_col(j, result_vect);
11232 }
11233 }
11234 else
11235 {
11236 M.reinit(M1.m, M2.m, 0);
11237 }
11238}
11239
11240
11271template <int spacedim, typename Number = double>
11272void
11276{
11277 AssertDimension(M1.m, M2.m);
11278
11279 if (M1.rank > 0 && M1.formal_rank > 0)
11280 {
11286 Vector<Number> col_vect_in_A(M1.A.m());
11287 Vector<Number> result_vect(M2.n);
11288
11293 M.reinit(M1.n, M2.n, M1.formal_rank);
11294 M.A = M1.B;
11295
11300 for (size_t j = 0; j < M.formal_rank; j++)
11301 {
11302 M1.A.get_column(j, col_vect_in_A);
11303 result_vect = Number(0.);
11304 M2.Tvmult(result_vect, col_vect_in_A, M2, M2.get_property());
11305
11309 M.B.fill_col(j, result_vect);
11310 }
11311 }
11312 else
11313 {
11314 M.reinit(M1.n, M2.n, 0);
11315 }
11316}
11317
11318
11352template <int spacedim, typename Number = double>
11353void
11354rk_h_Tmmult(const Number alpha,
11355 const RkMatrix<Number> &M1,
11358{
11359 AssertDimension(M1.m, M2.m);
11360
11361 if (M1.rank > 0 && M1.formal_rank > 0)
11362 {
11368 Vector<Number> col_vect_in_A(M1.A.m());
11369 Vector<Number> result_vect(M2.n);
11370
11375 M.reinit(M1.n, M2.n, M1.formal_rank);
11376 M.A = M1.B;
11377
11382 for (size_t j = 0; j < M.formal_rank; j++)
11383 {
11384 M1.A.get_column(j, col_vect_in_A);
11385 result_vect = Number(0.);
11386 M2.Tvmult(result_vect, alpha, col_vect_in_A, M2, M2.get_property());
11387
11391 M.B.fill_col(j, result_vect);
11392 }
11393 }
11394 else
11395 {
11396 M.reinit(M1.n, M2.n, 0);
11397 }
11398}
11399
11400
11409template <int spacedim, typename Number = double>
11410void
11414 bool is_M1M2_last_in_M_Sigma_P = true)
11415{
11416 Assert(M1->type == RkMatrixType, ExcInvalidHMatrixType(M1->type));
11417 Assert(M1->rkmatrix, ExcInternalError());
11418 // Assert(*(M1->col_index_range) == *(M2->row_index_range),
11419 // ExcMessage("Incompatible index sets during matrix
11420 // multiplication"));
11421 AssertDimension(M1->n, M2->m);
11422
11423 // // DEBUG
11424 // print_h_h_submatrix_mmult_accessor(std::cout, "M1", *M1, "M2", *M2);
11425
11426 if (is_M1M2_last_in_M_Sigma_P)
11427 {
11428 M->Sigma_P.pop_back();
11429 }
11430 else
11431 {
11433 }
11434
11435 RkMatrix<Number> *M_rk = new RkMatrix<Number>();
11436 rk_h_mmult(*(M1->rkmatrix), *M2, *M_rk);
11437 M->Sigma_R.push_back(M_rk);
11438
11439 // // DEBUG
11440 // LAPACKFullMatrixExt<Number> M_rk_to_full;
11441 // M_rk->convertToFullMatrix(M_rk_to_full);
11442 // M_rk_to_full.print_formatted(std::cout, 8, false, 16, "0");
11443
11444 AssertDimension(M->Sigma_F.size(), 0);
11445 M->type = RkMatrixType;
11446}
11447
11448
11458template <int spacedim, typename Number = double>
11459void
11463{
11464 AssertDimension(M1.n, M2.m());
11465
11466 Vector<Number> col_vect_in_M2(M2.m());
11467 Vector<Number> result_vect(M1.m);
11468
11469 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m;
11470 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n();
11471
11472 M.reinit(n_rows, n_cols);
11473 for (typename LAPACKFullMatrixExt<Number>::size_type j = 0; j < n_cols; j++)
11474 {
11475 M2.get_column(j, col_vect_in_M2);
11476 result_vect = Number(0.);
11477 M1.vmult(result_vect, col_vect_in_M2, M1, M1.get_property());
11478 M.fill_col(j, result_vect);
11479 }
11480}
11481
11482
11494template <int spacedim, typename Number = double>
11495void
11496h_f_mmult(const Number alpha,
11500{
11501 AssertDimension(M1.n, M2.m());
11502
11503 Vector<Number> col_vect_in_M2(M2.m());
11504 Vector<Number> result_vect(M1.m);
11505
11506 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m;
11507 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n();
11508
11509 M.reinit(n_rows, n_cols);
11510 for (typename LAPACKFullMatrixExt<Number>::size_type j = 0; j < n_cols; j++)
11511 {
11512 M2.get_column(j, col_vect_in_M2);
11513 result_vect = Number(0.);
11514 M1.vmult(result_vect, alpha, col_vect_in_M2, M1, M1.get_property());
11515 M.fill_col(j, result_vect);
11516 }
11517}
11518
11519
11530template <int spacedim, typename Number = double>
11531void
11535{
11536 AssertDimension(M1.n, M2.n());
11537
11538 Vector<Number> row_vect_in_M2(M2.n());
11539 Vector<Number> result_vect(M1.m);
11540
11541 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m;
11542 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.m();
11543
11544 M.reinit(n_rows, n_cols);
11545 for (typename LAPACKFullMatrixExt<Number>::size_type j = 0; j < n_cols; j++)
11546 {
11547 M2.get_row(j, row_vect_in_M2);
11548 result_vect = Number(0.);
11549 M1.vmult(result_vect, row_vect_in_M2, M1, M1.get_property());
11550 M.fill_col(j, result_vect);
11551 }
11552}
11553
11554
11565template <int spacedim, typename Number = double>
11566void
11567h_f_mTmult(const Number alpha,
11571{
11572 AssertDimension(M1.n, M2.n());
11573
11574 Vector<Number> row_vect_in_M2(M2.n());
11575 Vector<Number> result_vect(M1.m);
11576
11577 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m;
11578 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.m();
11579
11580 M.reinit(n_rows, n_cols);
11581 for (typename LAPACKFullMatrixExt<Number>::size_type j = 0; j < n_cols; j++)
11582 {
11583 M2.get_row(j, row_vect_in_M2);
11584 result_vect = Number(0.);
11585 M1.vmult(result_vect, alpha, row_vect_in_M2, M1, M1.get_property());
11586 M.fill_col(j, result_vect);
11587 }
11588}
11589
11590
11601template <int spacedim, typename Number = double>
11602void
11606{
11607 AssertDimension(M1.m, M2.m());
11608
11609 Vector<Number> col_vect_in_M2(M2.m());
11610 Vector<Number> result_vect(M1.n);
11611
11612 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.n;
11613 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n();
11614
11615 M.reinit(n_rows, n_cols);
11616 for (typename LAPACKFullMatrixExt<Number>::size_type j = 0; j < n_cols; j++)
11617 {
11618 M2.get_column(j, col_vect_in_M2);
11619 result_vect = Number(0.);
11620 M1.Tvmult(result_vect, col_vect_in_M2, M1, M1.get_property());
11621 M.fill_col(j, result_vect);
11622 }
11623}
11624
11625
11626template <int spacedim, typename Number = double>
11627void
11628h_f_Tmmult(const Number alpha,
11632{
11633 AssertDimension(M1.m, M2.m());
11634
11635 Vector<Number> col_vect_in_M2(M2.m());
11636 Vector<Number> result_vect(M1.n);
11637
11638 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.n;
11639 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n();
11640
11641 M.reinit(n_rows, n_cols);
11642 for (typename LAPACKFullMatrixExt<Number>::size_type j = 0; j < n_cols; j++)
11643 {
11644 M2.get_column(j, col_vect_in_M2);
11645 result_vect = Number(0.);
11646 M1.Tvmult(result_vect, alpha, col_vect_in_M2, M1, M1.get_property());
11647 M.fill_col(j, result_vect);
11648 }
11649}
11650
11651
11667template <int spacedim, typename Number = double>
11668void
11672{
11673 AssertDimension(M1.n, M2.m());
11674
11678 LAPACKFullMatrixExt<Number> M2_copy(M2);
11679
11683 RkMatrix<Number> M2_rk(M2_copy);
11684
11685 h_rk_mmult(M1, M2_rk, M);
11686}
11687
11688
11705template <int spacedim, typename Number = double>
11706void
11707h_f_mmult(const Number alpha,
11711{
11712 AssertDimension(M1.n, M2.m());
11713
11717 LAPACKFullMatrixExt<Number> M2_copy(M2);
11718
11722 RkMatrix<Number> M2_rk(M2_copy);
11723
11724 h_rk_mmult(alpha, M1, M2_rk, M);
11725}
11726
11727
11744template <int spacedim, typename Number = double>
11745void
11749{
11750 AssertDimension(M1.n, M2.n());
11751
11755 LAPACKFullMatrixExt<Number> M2_copy(M2);
11756
11760 RkMatrix<Number> M2_rk(M2_copy);
11761
11762 h_rk_mTmult(M1, M2_rk, M);
11763}
11764
11765
11782template <int spacedim, typename Number = double>
11783void
11784h_f_mTmult(const Number alpha,
11788{
11789 AssertDimension(M1.n, M2.n());
11790
11794 LAPACKFullMatrixExt<Number> M2_copy(M2);
11795
11799 RkMatrix<Number> M2_rk(M2_copy);
11800
11801 h_rk_mTmult(alpha, M1, M2_rk, M);
11802}
11803
11804
11821template <int spacedim, typename Number = double>
11822void
11826{
11827 AssertDimension(M1.m, M2.m());
11828
11832 LAPACKFullMatrixExt<Number> M2_copy(M2);
11833
11837 RkMatrix<Number> M2_rk(M2_copy);
11838
11839 h_rk_Tmmult(M1, M2_rk, M);
11840}
11841
11842
11860template <int spacedim, typename Number = double>
11861void
11862h_f_Tmmult(const Number alpha,
11866{
11867 AssertDimension(M1.m, M2.m());
11868
11872 LAPACKFullMatrixExt<Number> M2_copy(M2);
11873
11877 RkMatrix<Number> M2_rk(M2_copy);
11878
11879 h_rk_Tmmult(alpha, M1, M2_rk, M);
11880}
11881
11882
11892template <int spacedim, typename Number = double>
11893void
11895 const HMatrix<spacedim, Number> *M2,
11897 bool is_M1M2_last_in_M_Sigma_P = true)
11898{
11899 Assert(M2->type == FullMatrixType, ExcInvalidHMatrixType(M2->type));
11900 Assert(M2->fullmatrix, ExcInternalError());
11901 // Assert(*(M1->col_index_range) == *(M2->row_index_range),
11902 // ExcMessage("Incompatible index sets during matrix
11903 // multiplication"));
11904 AssertDimension(M1->n, M2->m);
11905
11906 // // DEBUG
11907 // print_h_h_submatrix_mmult_accessor(std::cout, "M1", *M1, "M2", *M2);
11908
11909 if (is_M1M2_last_in_M_Sigma_P)
11910 {
11911 M->Sigma_P.pop_back();
11912 }
11913 else
11914 {
11916 }
11917
11918 if (M->bc_node->get_data_reference().get_is_near_field())
11919 {
11924 h_f_mmult(*M1, *(M2->fullmatrix), *M_full);
11925 M->Sigma_F.push_back(M_full);
11926
11927 // // DEBUG
11928 // M_full->print_formatted(std::cout, 8, false, 16, "0");
11929
11930 AssertDimension(M->Sigma_R.size(), 0);
11931 M->type = FullMatrixType;
11932 }
11933 else
11934 {
11938 RkMatrix<Number> *M_rk = new RkMatrix<Number>();
11939 h_f_mmult(*M1, *(M2->fullmatrix), *M_rk);
11940 M->Sigma_R.push_back(M_rk);
11941
11942 // // DEBUG
11943 // LAPACKFullMatrixExt<Number> M_rk_to_full;
11944 // M_rk->convertToFullMatrix(M_rk_to_full);
11945 // M_rk_to_full.print_formatted(std::cout, 8, false, 16, "0");
11946
11947 AssertDimension(M->Sigma_F.size(), 0);
11948 M->type = RkMatrixType;
11949 }
11950}
11951
11952
11962template <int spacedim, typename Number = double>
11963void
11967{
11968 AssertDimension(M1.n(), M2.m);
11969
11970 Vector<Number> row_vect_in_M1(M1.n());
11971 Vector<Number> result_vect(M2.n);
11972
11973 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m();
11974 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n;
11975
11976 M.reinit(n_rows, n_cols);
11977 for (typename LAPACKFullMatrixExt<Number>::size_type i = 0; i < n_rows; i++)
11978 {
11979 M1.get_row(i, row_vect_in_M1);
11980 result_vect = Number(0.);
11981 M2.Tvmult(result_vect, row_vect_in_M1, M2, M2.get_property());
11982 M.fill_row(i, result_vect);
11983 }
11984}
11985
11986
11997template <int spacedim, typename Number = double>
11998void
11999f_h_mmult(const Number alpha,
12003{
12004 AssertDimension(M1.n(), M2.m);
12005
12006 Vector<Number> row_vect_in_M1(M1.n());
12007 Vector<Number> result_vect(M2.n);
12008
12009 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m();
12010 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n;
12011
12012 M.reinit(n_rows, n_cols);
12013 for (typename LAPACKFullMatrixExt<Number>::size_type i = 0; i < n_rows; i++)
12014 {
12015 M1.get_row(i, row_vect_in_M1);
12020 result_vect = Number(0.);
12021 M2.Tvmult(result_vect, alpha, row_vect_in_M1, M2, M2.get_property());
12022 M.fill_row(i, result_vect);
12023 }
12024}
12025
12026
12036template <int spacedim, typename Number = double>
12037void
12041{
12042 AssertDimension(M1.n(), M2.n);
12043
12044 Vector<Number> row_vect_in_M1(M1.n());
12045 Vector<Number> result_vect(M2.m);
12046
12047 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m();
12048 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.m;
12049
12050 M.reinit(n_rows, n_cols);
12051 for (typename LAPACKFullMatrixExt<Number>::size_type i = 0; i < n_rows; i++)
12052 {
12053 M1.get_row(i, row_vect_in_M1);
12054 result_vect = Number(0.);
12055 M2.vmult(result_vect, row_vect_in_M1, M2, M2.get_property());
12056 M.fill_row(i, result_vect);
12057 }
12058}
12059
12060
12071template <int spacedim, typename Number = double>
12072void
12073f_h_mTmult(const Number alpha,
12077{
12078 AssertDimension(M1.n(), M2.n);
12079
12080 Vector<Number> row_vect_in_M1(M1.n());
12081 Vector<Number> result_vect(M2.m);
12082
12083 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.m();
12084 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.m;
12085
12086 M.reinit(n_rows, n_cols);
12087 for (typename LAPACKFullMatrixExt<Number>::size_type i = 0; i < n_rows; i++)
12088 {
12089 M1.get_row(i, row_vect_in_M1);
12090 result_vect = Number(0.);
12091 M2.vmult(result_vect, alpha, row_vect_in_M1, M2, M2.get_property());
12092 M.fill_row(i, result_vect);
12093 }
12094}
12095
12096
12105template <int spacedim, typename Number = double>
12106void
12110{
12111 AssertDimension(M1.m(), M2.m);
12112
12113 Vector<Number> col_vect_in_M1(M1.m());
12114 Vector<Number> result_vect(M2.n);
12115
12116 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.n();
12117 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n;
12118
12119 M.reinit(n_rows, n_cols);
12120 for (typename LAPACKFullMatrixExt<Number>::size_type i = 0; i < n_rows; i++)
12121 {
12122 M1.get_column(i, col_vect_in_M1);
12123 result_vect = Number(0.);
12124 M2.Tvmult(result_vect, col_vect_in_M1, M2, M2.get_property());
12125 M.fill_row(i, result_vect);
12126 }
12127}
12128
12129
12139template <int spacedim, typename Number = double>
12140void
12141f_h_Tmmult(const Number alpha,
12145{
12146 AssertDimension(M1.m(), M2.m);
12147
12148 Vector<Number> col_vect_in_M1(M1.m());
12149 Vector<Number> result_vect(M2.n);
12150
12151 const typename LAPACKFullMatrixExt<Number>::size_type n_rows = M1.n();
12152 const typename LAPACKFullMatrixExt<Number>::size_type n_cols = M2.n;
12153
12154 M.reinit(n_rows, n_cols);
12155 for (typename LAPACKFullMatrixExt<Number>::size_type i = 0; i < n_rows; i++)
12156 {
12157 M1.get_column(i, col_vect_in_M1);
12158 result_vect = Number(0.);
12159 M2.Tvmult(result_vect, alpha, col_vect_in_M1, M2, M2.get_property());
12160 M.fill_row(i, result_vect);
12161 }
12162}
12163
12164
12173template <int spacedim, typename Number = double>
12174void
12178{
12179 AssertDimension(M1.n(), M2.m);
12180
12185 LAPACKFullMatrixExt<Number> M1_copy(M1);
12186 RkMatrix<Number> M1_rk(M1_copy);
12187 rk_h_mmult(M1_rk, M2, M);
12188}
12189
12190
12201template <int spacedim, typename Number = double>
12202void
12203f_h_mmult(const Number alpha,
12207{
12208 AssertDimension(M1.n(), M2.m);
12209
12214 LAPACKFullMatrixExt<Number> M1_copy(M1);
12215 RkMatrix<Number> M1_rk(M1_copy);
12216 rk_h_mmult(alpha, M1_rk, M2, M);
12217}
12218
12219
12229template <int spacedim, typename Number = double>
12230void
12234{
12235 AssertDimension(M1.n(), M2.n);
12236
12241 LAPACKFullMatrixExt<Number> M1_copy(M1);
12242 RkMatrix<Number> M1_rk(M1_copy);
12243 rk_h_mTmult(M1_rk, M2, M);
12244}
12245
12246
12257template <int spacedim, typename Number = double>
12258void
12259f_h_mTmult(const Number alpha,
12263{
12264 AssertDimension(M1.n(), M2.n);
12265
12270 LAPACKFullMatrixExt<Number> M1_copy(M1);
12271 RkMatrix<Number> M1_rk(M1_copy);
12272 rk_h_mTmult(alpha, M1_rk, M2, M);
12273}
12274
12275
12285template <int spacedim, typename Number = double>
12286void
12290{
12291 AssertDimension(M1.m(), M2.m);
12292
12297 LAPACKFullMatrixExt<Number> M1_copy(M1);
12298 RkMatrix<Number> M1_rk(M1_copy);
12299 rk_h_Tmmult(M1_rk, M2, M);
12300}
12301
12302
12312template <int spacedim, typename Number = double>
12313void
12314f_h_Tmmult(const Number alpha,
12318{
12319 AssertDimension(M1.m(), M2.m);
12320
12325 LAPACKFullMatrixExt<Number> M1_copy(M1);
12326 RkMatrix<Number> M1_rk(M1_copy);
12327 rk_h_Tmmult(alpha, M1_rk, M2, M);
12328}
12329
12330
12340template <int spacedim, typename Number = double>
12341void
12345 bool is_M1M2_last_in_M_Sigma_P = true)
12346{
12347 Assert(M1->type == FullMatrixType, ExcInvalidHMatrixType(M1->type));
12348 Assert(M1->fullmatrix, ExcInternalError());
12349 // Assert(*(M1->col_index_range) == *(M2->row_index_range),
12350 // ExcMessage("Incompatible index sets during matrix
12351 // multiplication"));
12352 AssertDimension(M1->n, M2->m);
12353
12354 // DEBUG
12355 // print_h_h_submatrix_mmult_accessor(std::cout, "M1", *M1, "M2", *M2);
12356
12357 if (is_M1M2_last_in_M_Sigma_P)
12358 {
12359 M->Sigma_P.pop_back();
12360 }
12361 else
12362 {
12364 }
12365
12366 if (M->bc_node->get_data_reference().get_is_near_field())
12367 {
12372 f_h_mmult(*(M1->fullmatrix), *M2, *M_full);
12373 M->Sigma_F.push_back(M_full);
12374
12375 // // DEBUG
12376 // M_full->print_formatted(std::cout, 8, false, 16, "0");
12377
12378 AssertDimension(M->Sigma_R.size(), 0);
12379 M->type = FullMatrixType;
12380 }
12381 else
12382 {
12386 RkMatrix<Number> *M_rk = new RkMatrix<Number>();
12387 f_h_mmult(*(M1->fullmatrix), *M2, *M_rk);
12388 M->Sigma_R.push_back(M_rk);
12389
12390 // // DEBUG
12391 // LAPACKFullMatrixExt<Number> M_rk_to_full;
12392 // M_rk->convertToFullMatrix(M_rk_to_full);
12393 // M_rk_to_full.print_formatted(std::cout, 8, false, 16, "0");
12394
12395 AssertDimension(M->Sigma_F.size(), 0);
12396 M->type = RkMatrixType;
12397 }
12398}
12399
12400
12401template <int spacedim, typename Number = double>
12402void
12405 BlockClusterTree<spacedim, typename numbers::NumberTraits<Number>::real_type>
12406 &Tind)
12407{
12409
12410 if (M->Sigma_P.size() > 0)
12411 {
12416 TreeNodeSplitMode split_mode_of_mm =
12418
12419 switch (split_mode_of_mm)
12420 {
12421 case HorizontalSplitMode: {
12423
12424 Assert(
12425 false,
12426 ExcMessage(
12427 "For level conserving H-matrix multiplication, HorizontalSplitMode should not appear!"));
12428
12429 break;
12430 }
12431 case VerticalSplitMode: {
12432 M->h_h_mmult_vertical_split(Tind);
12433
12434 Assert(
12435 false,
12436 ExcMessage(
12437 "For level conserving H-matrix multiplication, VerticalSplitMode should not appear!"));
12438
12439 break;
12440 }
12441 case CrossSplitMode: {
12442 M->h_h_mmult_cross_split(Tind);
12443
12444 break;
12445 }
12446 default: {
12447 Assert(
12448 false,
12449 ExcMessage(
12450 "Inconsistent case met during H-matrix MM multiplication"));
12451
12452 break;
12453 }
12454 }
12455
12463 AssertDimension(M->Sigma_P.size(), 0);
12464 for (HMatrix<spacedim, Number> *submatrix : M->submatrices)
12465 {
12466 h_h_mmult_phase1_recursion(submatrix, Tind);
12467 }
12468 }
12469}
12470
12471
12472template <int spacedim, typename Number = double>
12473void
12476 BlockClusterTree<spacedim, typename numbers::NumberTraits<Number>::real_type>
12477 &target_bc_tree,
12478 const unsigned int fixed_rank)
12479{
12483 for (HMatrix<spacedim, Number> *hmat : M.leaf_set)
12484 {
12490 AssertDimension(hmat->Sigma_P.size(), 0);
12491
12492 if (hmat->Sigma_R.size() > 0 && hmat->Sigma_F.size() == 0)
12493 {
12494 Assert(hmat->type == RkMatrixType, ExcInvalidHMatrixType(hmat->type));
12495
12502 Assert(
12503 hmat->rkmatrix == nullptr,
12504 ExcMessage(
12505 "The pointer hmat->rkmatrix should be nullptr before the following assignment:\n\nhmat->rkmatrix = hmat->Sigma_R[0];\n"));
12506 hmat->rkmatrix = hmat->Sigma_R[0];
12507 for (size_t i = 1; i < hmat->Sigma_R.size(); i++)
12508 {
12509 hmat->rkmatrix->add(*(hmat->Sigma_R[i]), fixed_rank);
12510 delete hmat->Sigma_R[i];
12511 hmat->Sigma_R[i] = nullptr;
12512 }
12513
12518 hmat->Sigma_R.clear();
12519 }
12520 else if (hmat->Sigma_R.size() == 0 && hmat->Sigma_F.size() > 0)
12521 {
12522 Assert(hmat->type == FullMatrixType,
12523 ExcInvalidHMatrixType(hmat->type));
12524
12525 Assert(
12526 hmat->fullmatrix == nullptr,
12527 ExcMessage(
12528 "The pointer hmat->fullmatrix should be nullptr before the following assignment:\n\nhmat->fullmatrix = hmat->Sigma_F[0];\n"));
12529 hmat->fullmatrix = hmat->Sigma_F[0];
12530 for (size_t i = 1; i < hmat->Sigma_F.size(); i++)
12531 {
12532 hmat->fullmatrix->add(*(hmat->Sigma_F[i]));
12533 delete hmat->Sigma_F[i];
12534 hmat->Sigma_F[i] = nullptr;
12535 }
12536
12541 hmat->Sigma_F.clear();
12542 }
12543 else
12544 {
12545 Assert(false, ExcInternalError());
12546 }
12547 }
12548
12555
12560 target_bc_tree,
12561 fixed_rank);
12562}
12563
12564
12590template <int spacedim, typename Number>
12591void
12596 const HMatrixSupport::BlockType block_type_for_local_Z,
12597 const unsigned int fixed_rank,
12598 const bool is_result_matrix_store_tril_only = false)
12599{
12604 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
12605
12606 if (is_result_matrix_store_tril_only)
12607 {
12608 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
12609 M0.get_property() ==
12610 HMatrixSupport::Property::hermite_symmetric ||
12611 M0.get_property() == HMatrixSupport::Property::lower_triangular,
12612 ExcInvalidHMatrixProperty(M0.get_property()));
12613 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
12614 ExcInvalidHMatrixBlockType(M0.get_block_type()));
12615 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
12616 M.get_property() ==
12617 HMatrixSupport::Property::hermite_symmetric ||
12618 M.get_property() == HMatrixSupport::Property::lower_triangular,
12619 ExcInvalidHMatrixProperty(M.get_property()));
12620 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
12621 ExcInvalidHMatrixBlockType(M.get_block_type()));
12622 }
12623
12624 // Array of empty child pointers used for initializing a block
12625 // cluster tree node.
12626 const std::array<
12627 typename BlockClusterTree<
12628 spacedim,
12629 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
12631 spacedim,
12632 typename numbers::NumberTraits<Number>::real_type>::child_num>
12633 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
12634
12640 typename BlockClusterTree<spacedim,
12641 typename numbers::NumberTraits<Number>::real_type>::
12642 node_value_type current_product_bc_node(
12643 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
12644 M1.bc_node->get_data_reference().get_tau_node(),
12645 M2.bc_node->get_data_reference().get_sigma_node()),
12646 0,
12647 empty_child_pointers,
12648 nullptr,
12649 UnsplitMode);
12650
12656 if (M0.bc_node->get_data_reference().get_is_near_field())
12657 {
12658 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
12659
12660 current_product_bc_node.get_data_reference().set_is_near_field(true);
12661 }
12662 else
12663 {
12664 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
12665
12666 current_product_bc_node.get_data_reference().set_is_near_field(false);
12667 }
12668
12676 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
12677 bool is_result_matrix_Z_store_tril_only = false;
12678
12679 if (is_result_matrix_store_tril_only &&
12681 {
12686 Z_property = M.property;
12687 is_result_matrix_Z_store_tril_only = true;
12688
12694 Assert(block_type_for_local_Z ==
12695 HMatrixSupport::BlockType::diagonal_block,
12696 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
12697 }
12698
12704 HMatrix<spacedim, Number> Z(&current_product_bc_node,
12705 fixed_rank,
12706 Z_property,
12707 block_type_for_local_Z);
12708 // Local variable storing the rank-k matrix obtained from multiplication
12709 // involving leaf node.
12711 // Local variable storing the full matrix obtained from multiplication
12712 // involving leaf node.
12714 // The result matrix type for the multiplication involving leaf node.
12715 HMatrixType result_matrix_type = UndefinedMatrixType;
12716
12717 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
12718 {
12723 if (M1.type == RkMatrixType)
12724 {
12725 rk_h_mmult(*(M1.rkmatrix), M2, ZR);
12726 result_matrix_type = RkMatrixType;
12727 }
12728 else if (M2.type == RkMatrixType)
12729 {
12730 h_rk_mmult(M1, *(M2.rkmatrix), ZR);
12731 result_matrix_type = RkMatrixType;
12732 }
12733 else if (M1.type == FullMatrixType)
12734 {
12735 f_h_mmult(*(M1.fullmatrix), M2, ZF);
12736 result_matrix_type = FullMatrixType;
12737 }
12738 else if (M2.type == FullMatrixType)
12739 {
12740 h_f_mmult(M1, *(M2.fullmatrix), ZF);
12741 result_matrix_type = FullMatrixType;
12742 }
12743 else
12744 {
12745 Assert(false, ExcInternalError());
12746 result_matrix_type = UndefinedMatrixType;
12747 }
12748
12749 if (Z.type == RkMatrixType)
12750 {
12751 // The desired result should be a rank-k matrix.
12752 if (result_matrix_type == RkMatrixType)
12753 {
12754 *(Z.rkmatrix) = ZR;
12755 }
12756 else if (result_matrix_type == FullMatrixType)
12757 {
12758 // Convert the full matrix to rank-k matrix.
12759 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
12760 }
12761 else
12762 {
12763 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
12764 }
12765 }
12766 else if (Z.type == FullMatrixType)
12767 {
12768 // The desired result should be a full matrix.
12769 if (result_matrix_type == RkMatrixType)
12770 {
12771 // Convert the rank-k matrix to full matrix.
12773 }
12774 else if (result_matrix_type == FullMatrixType)
12775 {
12776 *(Z.fullmatrix) = ZF;
12777 }
12778 else
12779 {
12780 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
12781 }
12782
12790 if (is_result_matrix_Z_store_tril_only)
12791 {
12792 switch (Z.property)
12793 {
12794 case HMatrixSupport::Property::symmetric: {
12795 Z.fullmatrix->set_property(
12796 LAPACKSupport::Property::symmetric);
12797
12798 break;
12799 }
12800 case HMatrixSupport::Property::hermite_symmetric: {
12801 Z.fullmatrix->set_property(
12802 LAPACKSupport::Property::hermite_symmetric);
12803
12804 break;
12805 }
12806 case HMatrixSupport::Property::lower_triangular: {
12807 Z.fullmatrix->set_property(
12808 LAPACKSupport::Property::lower_triangular);
12809
12810 break;
12811 }
12812 default: {
12813 Assert(false, ExcInvalidHMatrixProperty(Z.property));
12814
12815 break;
12816 }
12817 }
12818 }
12819 }
12820 else
12821 {
12822 Assert(false, ExcInvalidHMatrixType(Z.type));
12823 }
12824 }
12825 else
12826 {
12835 const unsigned int local_fixed_rank =
12836 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
12837
12838 std::array<HMatrixSupport::BlockType,
12839 BlockClusterTree<spacedim,
12840 typename numbers::NumberTraits<
12841 Number>::real_type>::child_num>
12842 block_types_for_submatrices_of_local_Z;
12843 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
12844 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
12845
12847 Z,
12848 *(M1.submatrices[0]),
12849 *(M2.submatrices[0]),
12850 block_types_for_submatrices_of_local_Z[0],
12851 local_fixed_rank,
12852 is_result_matrix_Z_store_tril_only);
12854 Z,
12855 *(M1.submatrices[1]),
12856 *(M2.submatrices[2]),
12857 block_types_for_submatrices_of_local_Z[0],
12858 local_fixed_rank,
12859 is_result_matrix_Z_store_tril_only);
12860
12861 if ((!is_result_matrix_Z_store_tril_only) ||
12862 (is_result_matrix_Z_store_tril_only &&
12863 Z.property != HMatrixSupport::Property::symmetric &&
12864 Z.property != HMatrixSupport::Property::hermite_symmetric &&
12865 Z.property != HMatrixSupport::Property::lower_triangular))
12866 {
12878 Z,
12879 *(M1.submatrices[0]),
12880 *(M2.submatrices[1]),
12881 block_types_for_submatrices_of_local_Z[1],
12882 local_fixed_rank,
12883 is_result_matrix_Z_store_tril_only);
12885 Z,
12886 *(M1.submatrices[1]),
12887 *(M2.submatrices[3]),
12888 block_types_for_submatrices_of_local_Z[1],
12889 local_fixed_rank,
12890 is_result_matrix_Z_store_tril_only);
12891 }
12892
12894 Z,
12895 *(M1.submatrices[2]),
12896 *(M2.submatrices[0]),
12897 block_types_for_submatrices_of_local_Z[2],
12898 local_fixed_rank,
12899 is_result_matrix_Z_store_tril_only);
12901 Z,
12902 *(M1.submatrices[3]),
12903 *(M2.submatrices[2]),
12904 block_types_for_submatrices_of_local_Z[2],
12905 local_fixed_rank,
12906 is_result_matrix_Z_store_tril_only);
12907
12909 Z,
12910 *(M1.submatrices[2]),
12911 *(M2.submatrices[1]),
12912 block_types_for_submatrices_of_local_Z[3],
12913 local_fixed_rank,
12914 is_result_matrix_Z_store_tril_only);
12916 Z,
12917 *(M1.submatrices[3]),
12918 *(M2.submatrices[3]),
12919 block_types_for_submatrices_of_local_Z[3],
12920 local_fixed_rank,
12921 is_result_matrix_Z_store_tril_only);
12922 }
12923
12927 if (M0.bc_node->get_data_reference().get_is_near_field())
12928 {
12933 Assert(M.fullmatrix, ExcInternalError());
12934
12935 if ((!is_result_matrix_store_tril_only) ||
12936 (is_result_matrix_store_tril_only &&
12937 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
12938 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
12939 {
12940 M.fullmatrix->fill(*(Z.fullmatrix),
12941 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
12942 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
12943 0,
12944 0,
12945 Number(1.0),
12946 false,
12947 true);
12948 }
12949 }
12950 else
12951 {
12958 Assert(M.rkmatrix, ExcInternalError());
12959
12960 if ((!is_result_matrix_store_tril_only) ||
12961 (is_result_matrix_store_tril_only &&
12962 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
12963 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
12964 {
12965 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
12966 *M.col_index_range,
12967 *(Z.rkmatrix),
12968 *(Z.row_index_range),
12969 *(Z.col_index_range),
12970 fixed_rank);
12971 }
12972 }
12973}
12974
12975
13008template <int spacedim, typename Number>
13009void
13012 const Number alpha,
13015 const HMatrixSupport::BlockType block_type_for_local_Z,
13016 const unsigned int fixed_rank,
13017 const bool is_result_matrix_store_tril_only = false)
13018{
13023 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
13024
13025 if (is_result_matrix_store_tril_only)
13026 {
13027 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
13028 M0.get_property() ==
13029 HMatrixSupport::Property::hermite_symmetric ||
13030 M0.get_property() == HMatrixSupport::Property::lower_triangular,
13031 ExcInvalidHMatrixProperty(M0.get_property()));
13032 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
13033 ExcInvalidHMatrixBlockType(M0.get_block_type()));
13034 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
13035 M.get_property() ==
13036 HMatrixSupport::Property::hermite_symmetric ||
13037 M.get_property() == HMatrixSupport::Property::lower_triangular,
13038 ExcInvalidHMatrixProperty(M.get_property()));
13039 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
13040 ExcInvalidHMatrixBlockType(M.get_block_type()));
13041 }
13042
13043 // Array of empty child pointers used for initializing a block
13044 // cluster tree node.
13045 const std::array<
13046 typename BlockClusterTree<
13047 spacedim,
13048 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
13050 spacedim,
13051 typename numbers::NumberTraits<Number>::real_type>::child_num>
13052 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
13053
13059 typename BlockClusterTree<spacedim,
13060 typename numbers::NumberTraits<Number>::real_type>::
13061 node_value_type current_product_bc_node(
13062 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
13063 M1.bc_node->get_data_reference().get_tau_node(),
13064 M2.bc_node->get_data_reference().get_sigma_node()),
13065 0,
13066 empty_child_pointers,
13067 nullptr,
13068 UnsplitMode);
13069
13075 if (M0.bc_node->get_data_reference().get_is_near_field())
13076 {
13077 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
13078
13079 current_product_bc_node.get_data_reference().set_is_near_field(true);
13080 }
13081 else
13082 {
13083 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
13084
13085 current_product_bc_node.get_data_reference().set_is_near_field(false);
13086 }
13087
13095 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
13096 bool is_result_matrix_Z_store_tril_only = false;
13097
13098 if (is_result_matrix_store_tril_only &&
13100 {
13105 Z_property = M.property;
13106 is_result_matrix_Z_store_tril_only = true;
13107
13113 Assert(block_type_for_local_Z ==
13114 HMatrixSupport::BlockType::diagonal_block,
13115 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
13116 }
13117
13118
13124 HMatrix<spacedim, Number> Z(&current_product_bc_node,
13125 fixed_rank,
13126 Z_property,
13127 block_type_for_local_Z);
13128 // Local variable storing the rank-k matrix obtained from multiplication
13129 // involving leaf node.
13131 // Local variable storing the full matrix obtained from multiplication
13132 // involving leaf node.
13134 // The result matrix type for the multiplication involving leaf node.
13135 HMatrixType result_matrix_type = UndefinedMatrixType;
13136
13137 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
13138 {
13143 if (M1.type == RkMatrixType)
13144 {
13145 rk_h_mmult(alpha, *(M1.rkmatrix), M2, ZR);
13146 result_matrix_type = RkMatrixType;
13147 }
13148 else if (M2.type == RkMatrixType)
13149 {
13150 h_rk_mmult(alpha, M1, *(M2.rkmatrix), ZR);
13151 result_matrix_type = RkMatrixType;
13152 }
13153 else if (M1.type == FullMatrixType)
13154 {
13155 f_h_mmult(alpha, *(M1.fullmatrix), M2, ZF);
13156 result_matrix_type = FullMatrixType;
13157 }
13158 else if (M2.type == FullMatrixType)
13159 {
13160 h_f_mmult(alpha, M1, *(M2.fullmatrix), ZF);
13161 result_matrix_type = FullMatrixType;
13162 }
13163 else
13164 {
13165 Assert(false, ExcInternalError());
13166 result_matrix_type = UndefinedMatrixType;
13167 }
13168
13169 if (Z.type == RkMatrixType)
13170 {
13171 // The desired result should be a rank-k matrix.
13172 if (result_matrix_type == RkMatrixType)
13173 {
13174 *(Z.rkmatrix) = ZR;
13175 }
13176 else if (result_matrix_type == FullMatrixType)
13177 {
13178 // Convert the full matrix to rank-k matrix.
13179 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
13180 }
13181 else
13182 {
13183 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
13184 }
13185 }
13186 else if (Z.type == FullMatrixType)
13187 {
13188 // The desired result should be a full matrix.
13189 if (result_matrix_type == RkMatrixType)
13190 {
13191 // Convert the rank-k matrix to full matrix.
13193 }
13194 else if (result_matrix_type == FullMatrixType)
13195 {
13196 *(Z.fullmatrix) = ZF;
13197 }
13198 else
13199 {
13200 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
13201 }
13202
13210 if (is_result_matrix_Z_store_tril_only)
13211 {
13212 switch (Z.property)
13213 {
13214 case HMatrixSupport::Property::symmetric: {
13215 Z.fullmatrix->set_property(
13216 LAPACKSupport::Property::symmetric);
13217
13218 break;
13219 }
13220 case HMatrixSupport::Property::hermite_symmetric: {
13221 Z.fullmatrix->set_property(
13222 LAPACKSupport::Property::hermite_symmetric);
13223
13224 break;
13225 }
13226 case HMatrixSupport::Property::lower_triangular: {
13227 Z.fullmatrix->set_property(
13228 LAPACKSupport::Property::lower_triangular);
13229
13230 break;
13231 }
13232 default: {
13233 Assert(false, ExcInvalidHMatrixProperty(Z.property));
13234
13235 break;
13236 }
13237 }
13238 }
13239 }
13240 else
13241 {
13242 Assert(false, ExcInvalidHMatrixType(Z.type));
13243 }
13244 }
13245 else
13246 {
13255 const unsigned int local_fixed_rank =
13256 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
13257
13258 std::array<HMatrixSupport::BlockType,
13259 BlockClusterTree<spacedim,
13260 typename numbers::NumberTraits<
13261 Number>::real_type>::child_num>
13262 block_types_for_submatrices_of_local_Z;
13263 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
13264 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
13265
13267 Z,
13268 alpha,
13269 *(M1.submatrices[0]),
13270 *(M2.submatrices[0]),
13271 block_types_for_submatrices_of_local_Z[0],
13272 local_fixed_rank,
13273 is_result_matrix_Z_store_tril_only);
13275 Z,
13276 alpha,
13277 *(M1.submatrices[1]),
13278 *(M2.submatrices[2]),
13279 block_types_for_submatrices_of_local_Z[0],
13280 local_fixed_rank,
13281 is_result_matrix_Z_store_tril_only);
13282
13283 if ((!is_result_matrix_Z_store_tril_only) ||
13284 (is_result_matrix_Z_store_tril_only &&
13285 Z.property != HMatrixSupport::Property::symmetric &&
13286 Z.property != HMatrixSupport::Property::hermite_symmetric &&
13287 Z.property != HMatrixSupport::Property::lower_triangular))
13288 {
13304 Z,
13305 alpha,
13306 *(M1.submatrices[0]),
13307 *(M2.submatrices[1]),
13308 block_types_for_submatrices_of_local_Z[1],
13309 local_fixed_rank,
13310 is_result_matrix_Z_store_tril_only);
13312 Z,
13313 alpha,
13314 *(M1.submatrices[1]),
13315 *(M2.submatrices[3]),
13316 block_types_for_submatrices_of_local_Z[1],
13317 local_fixed_rank,
13318 is_result_matrix_Z_store_tril_only);
13319 }
13320
13322 Z,
13323 alpha,
13324 *(M1.submatrices[2]),
13325 *(M2.submatrices[0]),
13326 block_types_for_submatrices_of_local_Z[2],
13327 local_fixed_rank,
13328 is_result_matrix_Z_store_tril_only);
13330 Z,
13331 alpha,
13332 *(M1.submatrices[3]),
13333 *(M2.submatrices[2]),
13334 block_types_for_submatrices_of_local_Z[2],
13335 local_fixed_rank,
13336 is_result_matrix_Z_store_tril_only);
13337
13339 Z,
13340 alpha,
13341 *(M1.submatrices[2]),
13342 *(M2.submatrices[1]),
13343 block_types_for_submatrices_of_local_Z[3],
13344 local_fixed_rank,
13345 is_result_matrix_Z_store_tril_only);
13347 Z,
13348 alpha,
13349 *(M1.submatrices[3]),
13350 *(M2.submatrices[3]),
13351 block_types_for_submatrices_of_local_Z[3],
13352 local_fixed_rank,
13353 is_result_matrix_Z_store_tril_only);
13354 }
13355
13359 if (M0.bc_node->get_data_reference().get_is_near_field())
13360 {
13365 Assert(M.fullmatrix, ExcInternalError());
13366
13367 if ((!is_result_matrix_store_tril_only) ||
13368 (is_result_matrix_store_tril_only &&
13369 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
13370 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
13371 {
13372 M.fullmatrix->fill(*(Z.fullmatrix),
13373 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
13374 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
13375 0,
13376 0,
13377 Number(1.0),
13378 false,
13379 true);
13380 }
13381 }
13382 else
13383 {
13390 Assert(M.rkmatrix, ExcInternalError());
13391
13392 if ((!is_result_matrix_store_tril_only) ||
13393 (is_result_matrix_store_tril_only &&
13394 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
13395 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
13396 {
13397 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
13398 *M.col_index_range,
13399 *(Z.rkmatrix),
13400 *(Z.row_index_range),
13401 *(Z.col_index_range),
13402 fixed_rank);
13403 }
13404 }
13405}
13406
13407
13408template <int spacedim, typename Number>
13409void
13413 const Number alpha,
13416 const HMatrixSupport::BlockType block_type_for_local_Z,
13417 const unsigned int fixed_rank,
13418 const bool is_result_matrix_store_tril_only = false)
13419{
13424 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
13425
13426 if (is_result_matrix_store_tril_only)
13427 {
13428 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
13429 M0.get_property() ==
13430 HMatrixSupport::Property::hermite_symmetric ||
13431 M0.get_property() == HMatrixSupport::Property::lower_triangular,
13432 ExcInvalidHMatrixProperty(M0.get_property()));
13433 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
13434 ExcInvalidHMatrixBlockType(M0.get_block_type()));
13435 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
13436 M.get_property() ==
13437 HMatrixSupport::Property::hermite_symmetric ||
13438 M.get_property() == HMatrixSupport::Property::lower_triangular,
13439 ExcInvalidHMatrixProperty(M.get_property()));
13440 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
13441 ExcInvalidHMatrixBlockType(M.get_block_type()));
13442 }
13443
13444 // Array of empty child pointers used for initializing a block
13445 // cluster tree node.
13446 const std::array<
13447 typename BlockClusterTree<
13448 spacedim,
13449 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
13451 spacedim,
13452 typename numbers::NumberTraits<Number>::real_type>::child_num>
13453 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
13454
13460 typename BlockClusterTree<spacedim,
13461 typename numbers::NumberTraits<Number>::real_type>::
13462 node_value_type current_product_bc_node(
13463 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
13464 M1.bc_node->get_data_reference().get_tau_node(),
13465 M2.bc_node->get_data_reference().get_sigma_node()),
13466 0,
13467 empty_child_pointers,
13468 nullptr,
13469 UnsplitMode);
13470
13476 if (M0.bc_node->get_data_reference().get_is_near_field())
13477 {
13478 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
13479
13480 current_product_bc_node.get_data_reference().set_is_near_field(true);
13481 }
13482 else
13483 {
13484 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
13485
13486 current_product_bc_node.get_data_reference().set_is_near_field(false);
13487 }
13488
13496 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
13497 bool is_result_matrix_Z_store_tril_only = false;
13498
13499 if (is_result_matrix_store_tril_only &&
13501 {
13506 Z_property = M.property;
13507 is_result_matrix_Z_store_tril_only = true;
13508
13514 Assert(block_type_for_local_Z ==
13515 HMatrixSupport::BlockType::diagonal_block,
13516 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
13517 }
13518
13519
13525 HMatrix<spacedim, Number> Z(&current_product_bc_node,
13526 fixed_rank,
13527 Z_property,
13528 block_type_for_local_Z);
13529 // Local variable storing the rank-k matrix obtained from multiplication
13530 // involving leaf node.
13532 // Local variable storing the full matrix obtained from multiplication
13533 // involving leaf node.
13535 // The result matrix type for the multiplication involving leaf node.
13536 HMatrixType result_matrix_type = UndefinedMatrixType;
13537
13538 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
13539 {
13544 if (M1.type == RkMatrixType)
13545 {
13546 rk_h_mmult(alpha, *(M1.rkmatrix), M2, ZR);
13547 result_matrix_type = RkMatrixType;
13548 }
13549 else if (M2.type == RkMatrixType)
13550 {
13551 h_rk_mmult(alpha, M1, *(M2.rkmatrix), ZR);
13552 result_matrix_type = RkMatrixType;
13553 }
13554 else if (M1.type == FullMatrixType)
13555 {
13556 f_h_mmult(alpha, *(M1.fullmatrix), M2, ZF);
13557 result_matrix_type = FullMatrixType;
13558 }
13559 else if (M2.type == FullMatrixType)
13560 {
13561 h_f_mmult(alpha, M1, *(M2.fullmatrix), ZF);
13562 result_matrix_type = FullMatrixType;
13563 }
13564 else
13565 {
13566 Assert(false, ExcInternalError());
13567 result_matrix_type = UndefinedMatrixType;
13568 }
13569
13570 if (Z.type == RkMatrixType)
13571 {
13572 // The desired result should be a rank-k matrix.
13573 if (result_matrix_type == RkMatrixType)
13574 {
13575 *(Z.rkmatrix) = ZR;
13576 }
13577 else if (result_matrix_type == FullMatrixType)
13578 {
13579 // Convert the full matrix to rank-k matrix.
13580 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
13581 }
13582 else
13583 {
13584 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
13585 }
13586 }
13587 else if (Z.type == FullMatrixType)
13588 {
13589 // The desired result should be a full matrix.
13590 if (result_matrix_type == RkMatrixType)
13591 {
13592 // Convert the rank-k matrix to full matrix.
13594 }
13595 else if (result_matrix_type == FullMatrixType)
13596 {
13597 *(Z.fullmatrix) = ZF;
13598 }
13599 else
13600 {
13601 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
13602 }
13603
13611 if (is_result_matrix_Z_store_tril_only)
13612 {
13613 switch (Z.property)
13614 {
13615 case HMatrixSupport::Property::symmetric: {
13616 Z.fullmatrix->set_property(
13617 LAPACKSupport::Property::symmetric);
13618
13619 break;
13620 }
13621 case HMatrixSupport::Property::hermite_symmetric: {
13622 Z.fullmatrix->set_property(
13623 LAPACKSupport::Property::hermite_symmetric);
13624
13625 break;
13626 }
13627 case HMatrixSupport::Property::lower_triangular: {
13628 Z.fullmatrix->set_property(
13629 LAPACKSupport::Property::lower_triangular);
13630
13631 break;
13632 }
13633 default: {
13634 Assert(false, ExcInvalidHMatrixProperty(Z.property));
13635
13636 break;
13637 }
13638 }
13639 }
13640 }
13641 else
13642 {
13643 Assert(false, ExcInvalidHMatrixType(Z.type));
13644 }
13645 }
13646 else
13647 {
13656 const unsigned int local_fixed_rank =
13657 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
13658
13659 std::array<HMatrixSupport::BlockType,
13660 BlockClusterTree<spacedim,
13661 typename numbers::NumberTraits<
13662 Number>::real_type>::child_num>
13663 block_types_for_submatrices_of_local_Z;
13664 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
13665 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
13666
13668 M0,
13669 Z,
13670 alpha,
13671 *(M1.submatrices[0]),
13672 *(M2.submatrices[0]),
13673 block_types_for_submatrices_of_local_Z[0],
13674 local_fixed_rank,
13675 is_result_matrix_Z_store_tril_only);
13677 M0,
13678 Z,
13679 alpha,
13680 *(M1.submatrices[1]),
13681 *(M2.submatrices[2]),
13682 block_types_for_submatrices_of_local_Z[0],
13683 local_fixed_rank,
13684 is_result_matrix_Z_store_tril_only);
13685
13686 if ((!is_result_matrix_Z_store_tril_only) ||
13687 (is_result_matrix_Z_store_tril_only &&
13688 Z.property != HMatrixSupport::Property::symmetric &&
13689 Z.property != HMatrixSupport::Property::hermite_symmetric &&
13690 Z.property != HMatrixSupport::Property::lower_triangular))
13691 {
13707 M0,
13708 Z,
13709 alpha,
13710 *(M1.submatrices[0]),
13711 *(M2.submatrices[1]),
13712 block_types_for_submatrices_of_local_Z[1],
13713 local_fixed_rank,
13714 is_result_matrix_Z_store_tril_only);
13716 M0,
13717 Z,
13718 alpha,
13719 *(M1.submatrices[1]),
13720 *(M2.submatrices[3]),
13721 block_types_for_submatrices_of_local_Z[1],
13722 local_fixed_rank,
13723 is_result_matrix_Z_store_tril_only);
13724 }
13725
13727 M0,
13728 Z,
13729 alpha,
13730 *(M1.submatrices[2]),
13731 *(M2.submatrices[0]),
13732 block_types_for_submatrices_of_local_Z[2],
13733 local_fixed_rank,
13734 is_result_matrix_Z_store_tril_only);
13736 M0,
13737 Z,
13738 alpha,
13739 *(M1.submatrices[3]),
13740 *(M2.submatrices[2]),
13741 block_types_for_submatrices_of_local_Z[2],
13742 local_fixed_rank,
13743 is_result_matrix_Z_store_tril_only);
13744
13746 M0,
13747 Z,
13748 alpha,
13749 *(M1.submatrices[2]),
13750 *(M2.submatrices[1]),
13751 block_types_for_submatrices_of_local_Z[3],
13752 local_fixed_rank,
13753 is_result_matrix_Z_store_tril_only);
13755 M0,
13756 Z,
13757 alpha,
13758 *(M1.submatrices[3]),
13759 *(M2.submatrices[3]),
13760 block_types_for_submatrices_of_local_Z[3],
13761 local_fixed_rank,
13762 is_result_matrix_Z_store_tril_only);
13763 }
13764
13768 if (M0.bc_node->get_data_reference().get_is_near_field())
13769 {
13774 Assert(M.fullmatrix, ExcInternalError());
13775
13776 if ((!is_result_matrix_store_tril_only) ||
13777 (is_result_matrix_store_tril_only &&
13778 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
13779 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
13780 {
13786 std::unique_lock<std::mutex> ul(M0.update_lock, std::defer_lock);
13787 if (&M0 == &M)
13788 {
13789 ul.lock();
13790 }
13791
13792 M.fullmatrix->fill(*(Z.fullmatrix),
13793 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
13794 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
13795 0,
13796 0,
13797 Number(1.0),
13798 false,
13799 true);
13800 }
13801 }
13802 else
13803 {
13810 Assert(M.rkmatrix, ExcInternalError());
13811
13812 if ((!is_result_matrix_store_tril_only) ||
13813 (is_result_matrix_store_tril_only &&
13814 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
13815 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
13816 {
13822 std::unique_lock<std::mutex> ul(M0.update_lock, std::defer_lock);
13823 if (&M0 == &M)
13824 {
13825 ul.lock();
13826
13827#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 3
13828 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
13829 *M.col_index_range,
13830 *(Z.rkmatrix),
13831 *(Z.row_index_range),
13832 *(Z.col_index_range),
13833 fixed_rank);
13834#endif
13835
13836#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 1
13837 tbb::task_arena ta{ARENA_MAX_CONCURRENCY_IN_LU_AND_CHOL};
13838 ta.execute([&M, &Z, fixed_rank] {
13839 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
13840 *M.col_index_range,
13841 *(Z.rkmatrix),
13842 *(Z.row_index_range),
13843 *(Z.col_index_range),
13844 fixed_rank);
13845 });
13846#endif
13847
13848#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 2
13853 tbb::this_task_arena::isolate([&M, &Z, fixed_rank] {
13854 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
13855 *M.col_index_range,
13856 *(Z.rkmatrix),
13857 *(Z.row_index_range),
13858 *(Z.col_index_range),
13859 fixed_rank);
13860 });
13861#endif
13862 }
13863 else
13864 {
13865 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
13866 *M.col_index_range,
13867 *(Z.rkmatrix),
13868 *(Z.row_index_range),
13869 *(Z.col_index_range),
13870 fixed_rank);
13871 }
13872 }
13873 }
13874}
13875
13876
13908template <int spacedim, typename Number>
13909void
13915 const HMatrixSupport::BlockType block_type_for_local_Z,
13916 const unsigned int fixed_rank,
13917 const bool is_result_matrix_store_tril_only = false)
13918{
13923 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
13924
13925 if (is_result_matrix_store_tril_only)
13926 {
13927 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
13928 M0.get_property() ==
13929 HMatrixSupport::Property::hermite_symmetric ||
13930 M0.get_property() == HMatrixSupport::Property::lower_triangular,
13931 ExcInvalidHMatrixProperty(M0.get_property()));
13932 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
13933 ExcInvalidHMatrixBlockType(M0.get_block_type()));
13934 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
13935 M.get_property() ==
13936 HMatrixSupport::Property::hermite_symmetric ||
13937 M.get_property() == HMatrixSupport::Property::lower_triangular,
13938 ExcInvalidHMatrixProperty(M.get_property()));
13939 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
13940 ExcInvalidHMatrixBlockType(M.get_block_type()));
13941 }
13942
13943 // Array of empty child pointers used for initializing a block
13944 // cluster tree node.
13945 const std::array<
13946 typename BlockClusterTree<
13947 spacedim,
13948 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
13950 spacedim,
13951 typename numbers::NumberTraits<Number>::real_type>::child_num>
13952 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
13953
13963 typename BlockClusterTree<spacedim,
13964 typename numbers::NumberTraits<Number>::real_type>::
13965 node_value_type current_product_bc_node(
13966 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
13967 M1.bc_node->get_data_reference().get_tau_node(),
13968 M2.bc_node->get_data_reference().get_tau_node()),
13969 0,
13970 empty_child_pointers,
13971 nullptr,
13972 UnsplitMode);
13973
13979 if (M0.bc_node->get_data_reference().get_is_near_field())
13980 {
13981 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
13982
13983 current_product_bc_node.get_data_reference().set_is_near_field(true);
13984 }
13985 else
13986 {
13987 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
13988
13989 current_product_bc_node.get_data_reference().set_is_near_field(false);
13990 }
13991
14000 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
14001 bool is_result_matrix_Z_store_tril_only = false;
14002
14003 if (is_result_matrix_store_tril_only &&
14005 {
14010 Z_property = M.property;
14011 is_result_matrix_Z_store_tril_only = true;
14012
14018 Assert(block_type_for_local_Z ==
14019 HMatrixSupport::BlockType::diagonal_block,
14020 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
14021 }
14022
14028 HMatrix<spacedim, Number> Z(&current_product_bc_node,
14029 fixed_rank,
14030 Z_property,
14031 block_type_for_local_Z);
14032 // Local variable storing the rank-k matrix obtained from multiplication
14033 // involving leaf node.
14035 // Local variable storing the full matrix obtained from multiplication
14036 // involving leaf node.
14038 // The result matrix type for the multiplication involving leaf node.
14039 HMatrixType result_matrix_type = UndefinedMatrixType;
14040
14041 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
14042 {
14047 if (M1.type == RkMatrixType)
14048 {
14049 rk_h_mTmult(*(M1.rkmatrix), M2, ZR);
14050 result_matrix_type = RkMatrixType;
14051 }
14052 else if (M2.type == RkMatrixType)
14053 {
14054 h_rk_mTmult(M1, *(M2.rkmatrix), ZR);
14055 result_matrix_type = RkMatrixType;
14056 }
14057 else if (M1.type == FullMatrixType)
14058 {
14059 f_h_mTmult(*(M1.fullmatrix), M2, ZF);
14060 result_matrix_type = FullMatrixType;
14061 }
14062 else if (M2.type == FullMatrixType)
14063 {
14064 h_f_mTmult(M1, *(M2.fullmatrix), ZF);
14065 result_matrix_type = FullMatrixType;
14066 }
14067 else
14068 {
14069 Assert(false, ExcInternalError());
14070 result_matrix_type = UndefinedMatrixType;
14071 }
14072
14073 if (Z.type == RkMatrixType)
14074 {
14075 // The desired result should be a rank-k matrix.
14076 if (result_matrix_type == RkMatrixType)
14077 {
14078 *(Z.rkmatrix) = ZR;
14079 }
14080 else if (result_matrix_type == FullMatrixType)
14081 {
14082 // Convert the full matrix to rank-k matrix.
14083 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
14084 }
14085 else
14086 {
14087 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
14088 }
14089 }
14090 else if (Z.type == FullMatrixType)
14091 {
14092 // The desired result should be a full matrix.
14093 if (result_matrix_type == RkMatrixType)
14094 {
14095 // Convert the rank-k matrix to full matrix.
14097 }
14098 else if (result_matrix_type == FullMatrixType)
14099 {
14100 *(Z.fullmatrix) = ZF;
14101 }
14102 else
14103 {
14104 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
14105 }
14106
14114 if (is_result_matrix_Z_store_tril_only)
14115 {
14116 switch (Z.property)
14117 {
14118 case HMatrixSupport::Property::symmetric: {
14119 Z.fullmatrix->set_property(
14120 LAPACKSupport::Property::symmetric);
14121
14122 break;
14123 }
14124 case HMatrixSupport::Property::hermite_symmetric: {
14125 Z.fullmatrix->set_property(
14126 LAPACKSupport::Property::hermite_symmetric);
14127
14128 break;
14129 }
14130 case HMatrixSupport::Property::lower_triangular: {
14131 Z.fullmatrix->set_property(
14132 LAPACKSupport::Property::lower_triangular);
14133
14134 break;
14135 }
14136 default: {
14137 Assert(false, ExcInvalidHMatrixProperty(Z.property));
14138
14139 break;
14140 }
14141 }
14142 }
14143 }
14144 else
14145 {
14146 Assert(false, ExcInvalidHMatrixType(Z.type));
14147 }
14148 }
14149 else
14150 {
14159 const unsigned int local_fixed_rank =
14160 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
14161
14162 std::array<HMatrixSupport::BlockType,
14163 BlockClusterTree<spacedim,
14164 typename numbers::NumberTraits<
14165 Number>::real_type>::child_num>
14166 block_types_for_submatrices_of_local_Z;
14167 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
14168 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
14169
14171 Z,
14172 *(M1.submatrices[0]),
14173 *(M2.submatrices[0]),
14174 block_types_for_submatrices_of_local_Z[0],
14175 local_fixed_rank,
14176 is_result_matrix_Z_store_tril_only);
14178 Z,
14179 *(M1.submatrices[1]),
14180 *(M2.submatrices[1]),
14181 block_types_for_submatrices_of_local_Z[0],
14182 local_fixed_rank,
14183 is_result_matrix_Z_store_tril_only);
14184
14185 if ((!is_result_matrix_Z_store_tril_only) ||
14186 (is_result_matrix_Z_store_tril_only &&
14187 Z.property != HMatrixSupport::Property::symmetric &&
14188 Z.property != HMatrixSupport::Property::hermite_symmetric &&
14189 Z.property != HMatrixSupport::Property::lower_triangular))
14190 {
14202 Z,
14203 *(M1.submatrices[0]),
14204 *(M2.submatrices[2]),
14205 block_types_for_submatrices_of_local_Z[1],
14206 local_fixed_rank,
14207 is_result_matrix_Z_store_tril_only);
14209 Z,
14210 *(M1.submatrices[1]),
14211 *(M2.submatrices[3]),
14212 block_types_for_submatrices_of_local_Z[1],
14213 local_fixed_rank,
14214 is_result_matrix_Z_store_tril_only);
14215 }
14216
14218 Z,
14219 *(M1.submatrices[2]),
14220 *(M2.submatrices[0]),
14221 block_types_for_submatrices_of_local_Z[2],
14222 local_fixed_rank,
14223 is_result_matrix_Z_store_tril_only);
14225 Z,
14226 *(M1.submatrices[3]),
14227 *(M2.submatrices[1]),
14228 block_types_for_submatrices_of_local_Z[2],
14229 local_fixed_rank,
14230 is_result_matrix_Z_store_tril_only);
14231
14233 Z,
14234 *(M1.submatrices[2]),
14235 *(M2.submatrices[2]),
14236 block_types_for_submatrices_of_local_Z[3],
14237 local_fixed_rank,
14238 is_result_matrix_Z_store_tril_only);
14240 Z,
14241 *(M1.submatrices[3]),
14242 *(M2.submatrices[3]),
14243 block_types_for_submatrices_of_local_Z[3],
14244 local_fixed_rank,
14245 is_result_matrix_Z_store_tril_only);
14246 }
14247
14251 if (M0.bc_node->get_data_reference().get_is_near_field())
14252 {
14257 Assert(M.fullmatrix, ExcInternalError());
14258
14259 if ((!is_result_matrix_store_tril_only) ||
14260 (is_result_matrix_store_tril_only &&
14261 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
14262 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
14263 {
14264 M.fullmatrix->fill(*(Z.fullmatrix),
14265 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
14266 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
14267 0,
14268 0,
14269 Number(1.0),
14270 false,
14271 true);
14272 }
14273 }
14274 else
14275 {
14282 Assert(M.rkmatrix, ExcInternalError());
14283
14284 if ((!is_result_matrix_store_tril_only) ||
14285 (is_result_matrix_store_tril_only &&
14286 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
14287 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
14288 {
14289 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
14290 *M.col_index_range,
14291 *(Z.rkmatrix),
14292 *(Z.row_index_range),
14293 *(Z.col_index_range),
14294 fixed_rank);
14295 }
14296 }
14297}
14298
14299
14332template <int spacedim, typename Number>
14333void
14337 const Number alpha,
14340 const HMatrixSupport::BlockType block_type_for_local_Z,
14341 const unsigned int fixed_rank,
14342 const bool is_result_matrix_store_tril_only = false)
14343{
14348 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
14349
14350 if (is_result_matrix_store_tril_only)
14351 {
14352 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
14353 M0.get_property() ==
14354 HMatrixSupport::Property::hermite_symmetric ||
14355 M0.get_property() == HMatrixSupport::Property::lower_triangular,
14356 ExcInvalidHMatrixProperty(M0.get_property()));
14357 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
14358 ExcInvalidHMatrixBlockType(M0.get_block_type()));
14359 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
14360 M.get_property() ==
14361 HMatrixSupport::Property::hermite_symmetric ||
14362 M.get_property() == HMatrixSupport::Property::lower_triangular,
14363 ExcInvalidHMatrixProperty(M.get_property()));
14364 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
14365 ExcInvalidHMatrixBlockType(M.get_block_type()));
14366 }
14367
14368 // Array of empty child pointers used for initializing a block
14369 // cluster tree node.
14370 const std::array<
14371 typename BlockClusterTree<
14372 spacedim,
14373 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
14375 spacedim,
14376 typename numbers::NumberTraits<Number>::real_type>::child_num>
14377 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
14378
14388 typename BlockClusterTree<spacedim,
14389 typename numbers::NumberTraits<Number>::real_type>::
14390 node_value_type current_product_bc_node(
14391 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
14392 M1.bc_node->get_data_reference().get_tau_node(),
14393 M2.bc_node->get_data_reference().get_tau_node()),
14394 0,
14395 empty_child_pointers,
14396 nullptr,
14397 UnsplitMode);
14398
14404 if (M0.bc_node->get_data_reference().get_is_near_field())
14405 {
14406 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
14407
14408 current_product_bc_node.get_data_reference().set_is_near_field(true);
14409 }
14410 else
14411 {
14412 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
14413
14414 current_product_bc_node.get_data_reference().set_is_near_field(false);
14415 }
14416
14424 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
14425 bool is_result_matrix_Z_store_tril_only = false;
14426
14427 if (is_result_matrix_store_tril_only &&
14429 {
14434 Z_property = M.property;
14435 is_result_matrix_Z_store_tril_only = true;
14436
14442 Assert(block_type_for_local_Z ==
14443 HMatrixSupport::BlockType::diagonal_block,
14444 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
14445 }
14446
14452 HMatrix<spacedim, Number> Z(&current_product_bc_node,
14453 fixed_rank,
14454 Z_property,
14455 block_type_for_local_Z);
14456
14457 // Local variable storing the rank-k matrix obtained from multiplication
14458 // involving leaf node.
14460 // Local variable storing the full matrix obtained from multiplication
14461 // involving leaf node.
14463 // The result matrix type for the multiplication involving leaf node.
14464 HMatrixType result_matrix_type = UndefinedMatrixType;
14465
14466 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
14467 {
14472 if (M1.type == RkMatrixType)
14473 {
14474 rk_h_mTmult(alpha, *(M1.rkmatrix), M2, ZR);
14475 result_matrix_type = RkMatrixType;
14476 }
14477 else if (M2.type == RkMatrixType)
14478 {
14479 h_rk_mTmult(alpha, M1, *(M2.rkmatrix), ZR);
14480 result_matrix_type = RkMatrixType;
14481 }
14482 else if (M1.type == FullMatrixType)
14483 {
14484 f_h_mTmult(alpha, *(M1.fullmatrix), M2, ZF);
14485 result_matrix_type = FullMatrixType;
14486 }
14487 else if (M2.type == FullMatrixType)
14488 {
14489 h_f_mTmult(alpha, M1, *(M2.fullmatrix), ZF);
14490 result_matrix_type = FullMatrixType;
14491 }
14492 else
14493 {
14494 Assert(false, ExcInternalError());
14495 result_matrix_type = UndefinedMatrixType;
14496 }
14497
14498 if (Z.type == RkMatrixType)
14499 {
14500 // The desired result should be a rank-k matrix.
14501 if (result_matrix_type == RkMatrixType)
14502 {
14503 *(Z.rkmatrix) = ZR;
14504 }
14505 else if (result_matrix_type == FullMatrixType)
14506 {
14507 // Convert the full matrix to rank-k matrix.
14508 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
14509 }
14510 else
14511 {
14512 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
14513 }
14514 }
14515 else if (Z.type == FullMatrixType)
14516 {
14517 // The desired result should be a full matrix.
14518 if (result_matrix_type == RkMatrixType)
14519 {
14520 // Convert the rank-k matrix to full matrix.
14522 }
14523 else if (result_matrix_type == FullMatrixType)
14524 {
14525 *(Z.fullmatrix) = ZF;
14526 }
14527 else
14528 {
14529 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
14530 }
14531
14539 if (is_result_matrix_Z_store_tril_only)
14540 {
14541 switch (Z.property)
14542 {
14543 case HMatrixSupport::Property::symmetric: {
14544 Z.fullmatrix->set_property(
14545 LAPACKSupport::Property::symmetric);
14546
14547 break;
14548 }
14549 case HMatrixSupport::Property::hermite_symmetric: {
14550 Z.fullmatrix->set_property(
14551 LAPACKSupport::Property::hermite_symmetric);
14552
14553 break;
14554 }
14555 case HMatrixSupport::Property::lower_triangular: {
14556 Z.fullmatrix->set_property(
14557 LAPACKSupport::Property::lower_triangular);
14558
14559 break;
14560 }
14561 default: {
14562 Assert(false, ExcInvalidHMatrixProperty(Z.property));
14563
14564 break;
14565 }
14566 }
14567 }
14568 }
14569 else
14570 {
14571 Assert(false, ExcInvalidHMatrixType(Z.type));
14572 }
14573 }
14574 else
14575 {
14584 const unsigned int local_fixed_rank =
14585 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
14586
14587 std::array<HMatrixSupport::BlockType,
14588 BlockClusterTree<spacedim,
14589 typename numbers::NumberTraits<
14590 Number>::real_type>::child_num>
14591 block_types_for_submatrices_of_local_Z;
14592 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
14593 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
14594
14596 Z,
14597 alpha,
14598 *(M1.submatrices[0]),
14599 *(M2.submatrices[0]),
14600 block_types_for_submatrices_of_local_Z[0],
14601 local_fixed_rank,
14602 is_result_matrix_Z_store_tril_only);
14604 Z,
14605 alpha,
14606 *(M1.submatrices[1]),
14607 *(M2.submatrices[1]),
14608 block_types_for_submatrices_of_local_Z[0],
14609 local_fixed_rank,
14610 is_result_matrix_Z_store_tril_only);
14611
14612 if ((!is_result_matrix_Z_store_tril_only) ||
14613 (is_result_matrix_Z_store_tril_only &&
14614 Z.property != HMatrixSupport::Property::symmetric &&
14615 Z.property != HMatrixSupport::Property::hermite_symmetric &&
14616 Z.property != HMatrixSupport::Property::lower_triangular))
14617 {
14629 Z,
14630 alpha,
14631 *(M1.submatrices[0]),
14632 *(M2.submatrices[2]),
14633 block_types_for_submatrices_of_local_Z[1],
14634 local_fixed_rank,
14635 is_result_matrix_Z_store_tril_only);
14637 Z,
14638 alpha,
14639 *(M1.submatrices[1]),
14640 *(M2.submatrices[3]),
14641 block_types_for_submatrices_of_local_Z[1],
14642 local_fixed_rank,
14643 is_result_matrix_Z_store_tril_only);
14644 }
14645
14647 Z,
14648 alpha,
14649 *(M1.submatrices[2]),
14650 *(M2.submatrices[0]),
14651 block_types_for_submatrices_of_local_Z[2],
14652 local_fixed_rank,
14653 is_result_matrix_Z_store_tril_only);
14655 Z,
14656 alpha,
14657 *(M1.submatrices[3]),
14658 *(M2.submatrices[1]),
14659 block_types_for_submatrices_of_local_Z[2],
14660 local_fixed_rank,
14661 is_result_matrix_Z_store_tril_only);
14662
14664 Z,
14665 alpha,
14666 *(M1.submatrices[2]),
14667 *(M2.submatrices[2]),
14668 block_types_for_submatrices_of_local_Z[3],
14669 local_fixed_rank,
14670 is_result_matrix_Z_store_tril_only);
14672 Z,
14673 alpha,
14674 *(M1.submatrices[3]),
14675 *(M2.submatrices[3]),
14676 block_types_for_submatrices_of_local_Z[3],
14677 local_fixed_rank,
14678 is_result_matrix_Z_store_tril_only);
14679 }
14680
14684 if (M0.bc_node->get_data_reference().get_is_near_field())
14685 {
14690 Assert(M.fullmatrix, ExcInternalError());
14691
14692 if ((!is_result_matrix_store_tril_only) ||
14693 (is_result_matrix_store_tril_only &&
14694 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
14695 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
14696 {
14697 M.fullmatrix->fill(*(Z.fullmatrix),
14698 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
14699 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
14700 0,
14701 0,
14702 Number(1.0),
14703 false,
14704 true);
14705 }
14706 }
14707 else
14708 {
14715 Assert(M.rkmatrix, ExcInternalError());
14716
14717 if ((!is_result_matrix_store_tril_only) ||
14718 (is_result_matrix_store_tril_only &&
14719 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
14720 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
14721 {
14722 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
14723 *M.col_index_range,
14724 *(Z.rkmatrix),
14725 *(Z.row_index_range),
14726 *(Z.col_index_range),
14727 fixed_rank);
14728 }
14729 }
14730}
14731
14732
14733template <int spacedim, typename Number>
14734void
14738 const Number alpha,
14741 const HMatrixSupport::BlockType block_type_for_local_Z,
14742 const unsigned int fixed_rank,
14743 const bool is_result_matrix_store_tril_only = false)
14744{
14749 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
14750
14751 if (is_result_matrix_store_tril_only)
14752 {
14753 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
14754 M0.get_property() ==
14755 HMatrixSupport::Property::hermite_symmetric ||
14756 M0.get_property() == HMatrixSupport::Property::lower_triangular,
14757 ExcInvalidHMatrixProperty(M0.get_property()));
14758 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
14759 ExcInvalidHMatrixBlockType(M0.get_block_type()));
14760 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
14761 M.get_property() ==
14762 HMatrixSupport::Property::hermite_symmetric ||
14763 M.get_property() == HMatrixSupport::Property::lower_triangular,
14764 ExcInvalidHMatrixProperty(M.get_property()));
14765 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
14766 ExcInvalidHMatrixBlockType(M.get_block_type()));
14767 }
14768
14769 // Array of empty child pointers used for initializing a block
14770 // cluster tree node.
14771 const std::array<
14772 typename BlockClusterTree<
14773 spacedim,
14774 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
14776 spacedim,
14777 typename numbers::NumberTraits<Number>::real_type>::child_num>
14778 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
14779
14789 typename BlockClusterTree<spacedim,
14790 typename numbers::NumberTraits<Number>::real_type>::
14791 node_value_type current_product_bc_node(
14792 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
14793 M1.bc_node->get_data_reference().get_tau_node(),
14794 M2.bc_node->get_data_reference().get_tau_node()),
14795 0,
14796 empty_child_pointers,
14797 nullptr,
14798 UnsplitMode);
14799
14805 if (M0.bc_node->get_data_reference().get_is_near_field())
14806 {
14807 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
14808
14809 current_product_bc_node.get_data_reference().set_is_near_field(true);
14810 }
14811 else
14812 {
14813 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
14814
14815 current_product_bc_node.get_data_reference().set_is_near_field(false);
14816 }
14817
14825 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
14826 bool is_result_matrix_Z_store_tril_only = false;
14827
14828 if (is_result_matrix_store_tril_only &&
14830 {
14835 Z_property = M.property;
14836 is_result_matrix_Z_store_tril_only = true;
14837
14843 Assert(block_type_for_local_Z ==
14844 HMatrixSupport::BlockType::diagonal_block,
14845 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
14846 }
14847
14853 HMatrix<spacedim, Number> Z(&current_product_bc_node,
14854 fixed_rank,
14855 Z_property,
14856 block_type_for_local_Z);
14857
14858 // Local variable storing the rank-k matrix obtained from multiplication
14859 // involving leaf node.
14861 // Local variable storing the full matrix obtained from multiplication
14862 // involving leaf node.
14864 // The result matrix type for the multiplication involving leaf node.
14865 HMatrixType result_matrix_type = UndefinedMatrixType;
14866
14867 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
14868 {
14873 if (M1.type == RkMatrixType)
14874 {
14875 rk_h_mTmult(alpha, *(M1.rkmatrix), M2, ZR);
14876 result_matrix_type = RkMatrixType;
14877 }
14878 else if (M2.type == RkMatrixType)
14879 {
14880 h_rk_mTmult(alpha, M1, *(M2.rkmatrix), ZR);
14881 result_matrix_type = RkMatrixType;
14882 }
14883 else if (M1.type == FullMatrixType)
14884 {
14885 f_h_mTmult(alpha, *(M1.fullmatrix), M2, ZF);
14886 result_matrix_type = FullMatrixType;
14887 }
14888 else if (M2.type == FullMatrixType)
14889 {
14890 h_f_mTmult(alpha, M1, *(M2.fullmatrix), ZF);
14891 result_matrix_type = FullMatrixType;
14892 }
14893 else
14894 {
14895 Assert(false, ExcInternalError());
14896 result_matrix_type = UndefinedMatrixType;
14897 }
14898
14899 if (Z.type == RkMatrixType)
14900 {
14901 // The desired result should be a rank-k matrix.
14902 if (result_matrix_type == RkMatrixType)
14903 {
14904 *(Z.rkmatrix) = ZR;
14905 }
14906 else if (result_matrix_type == FullMatrixType)
14907 {
14908 // Convert the full matrix to rank-k matrix.
14909 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
14910 }
14911 else
14912 {
14913 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
14914 }
14915 }
14916 else if (Z.type == FullMatrixType)
14917 {
14918 // The desired result should be a full matrix.
14919 if (result_matrix_type == RkMatrixType)
14920 {
14921 // Convert the rank-k matrix to full matrix.
14923 }
14924 else if (result_matrix_type == FullMatrixType)
14925 {
14926 *(Z.fullmatrix) = ZF;
14927 }
14928 else
14929 {
14930 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
14931 }
14932
14940 if (is_result_matrix_Z_store_tril_only)
14941 {
14942 switch (Z.property)
14943 {
14944 case HMatrixSupport::Property::symmetric: {
14945 Z.fullmatrix->set_property(
14946 LAPACKSupport::Property::symmetric);
14947
14948 break;
14949 }
14950 case HMatrixSupport::Property::hermite_symmetric: {
14951 Z.fullmatrix->set_property(
14952 LAPACKSupport::Property::hermite_symmetric);
14953
14954 break;
14955 }
14956 case HMatrixSupport::Property::lower_triangular: {
14957 Z.fullmatrix->set_property(
14958 LAPACKSupport::Property::lower_triangular);
14959
14960 break;
14961 }
14962 default: {
14963 Assert(false, ExcInvalidHMatrixProperty(Z.property));
14964
14965 break;
14966 }
14967 }
14968 }
14969 }
14970 else
14971 {
14972 Assert(false, ExcInvalidHMatrixType(Z.type));
14973 }
14974 }
14975 else
14976 {
14985 const unsigned int local_fixed_rank =
14986 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
14987
14988 std::array<HMatrixSupport::BlockType,
14989 BlockClusterTree<spacedim,
14990 typename numbers::NumberTraits<
14991 Number>::real_type>::child_num>
14992 block_types_for_submatrices_of_local_Z;
14993 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
14994 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
14995
14997 M0,
14998 Z,
14999 alpha,
15000 *(M1.submatrices[0]),
15001 *(M2.submatrices[0]),
15002 block_types_for_submatrices_of_local_Z[0],
15003 local_fixed_rank,
15004 is_result_matrix_Z_store_tril_only);
15006 M0,
15007 Z,
15008 alpha,
15009 *(M1.submatrices[1]),
15010 *(M2.submatrices[1]),
15011 block_types_for_submatrices_of_local_Z[0],
15012 local_fixed_rank,
15013 is_result_matrix_Z_store_tril_only);
15014
15015 if ((!is_result_matrix_Z_store_tril_only) ||
15016 (is_result_matrix_Z_store_tril_only &&
15017 Z.property != HMatrixSupport::Property::symmetric &&
15018 Z.property != HMatrixSupport::Property::hermite_symmetric &&
15019 Z.property != HMatrixSupport::Property::lower_triangular))
15020 {
15032 M0,
15033 Z,
15034 alpha,
15035 *(M1.submatrices[0]),
15036 *(M2.submatrices[2]),
15037 block_types_for_submatrices_of_local_Z[1],
15038 local_fixed_rank,
15039 is_result_matrix_Z_store_tril_only);
15041 M0,
15042 Z,
15043 alpha,
15044 *(M1.submatrices[1]),
15045 *(M2.submatrices[3]),
15046 block_types_for_submatrices_of_local_Z[1],
15047 local_fixed_rank,
15048 is_result_matrix_Z_store_tril_only);
15049 }
15050
15052 M0,
15053 Z,
15054 alpha,
15055 *(M1.submatrices[2]),
15056 *(M2.submatrices[0]),
15057 block_types_for_submatrices_of_local_Z[2],
15058 local_fixed_rank,
15059 is_result_matrix_Z_store_tril_only);
15061 M0,
15062 Z,
15063 alpha,
15064 *(M1.submatrices[3]),
15065 *(M2.submatrices[1]),
15066 block_types_for_submatrices_of_local_Z[2],
15067 local_fixed_rank,
15068 is_result_matrix_Z_store_tril_only);
15069
15071 M0,
15072 Z,
15073 alpha,
15074 *(M1.submatrices[2]),
15075 *(M2.submatrices[2]),
15076 block_types_for_submatrices_of_local_Z[3],
15077 local_fixed_rank,
15078 is_result_matrix_Z_store_tril_only);
15080 M0,
15081 Z,
15082 alpha,
15083 *(M1.submatrices[3]),
15084 *(M2.submatrices[3]),
15085 block_types_for_submatrices_of_local_Z[3],
15086 local_fixed_rank,
15087 is_result_matrix_Z_store_tril_only);
15088 }
15089
15093 if (M0.bc_node->get_data_reference().get_is_near_field())
15094 {
15099 Assert(M.fullmatrix, ExcInternalError());
15100
15101 if ((!is_result_matrix_store_tril_only) ||
15102 (is_result_matrix_store_tril_only &&
15103 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
15104 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
15105 {
15111 std::unique_lock<std::mutex> ul(M0.update_lock, std::defer_lock);
15112 if (&M0 == &M)
15113 {
15114 ul.lock();
15115 }
15116
15117 M.fullmatrix->fill(*(Z.fullmatrix),
15118 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
15119 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
15120 0,
15121 0,
15122 Number(1.0),
15123 false,
15124 true);
15125 }
15126 }
15127 else
15128 {
15135 Assert(M.rkmatrix, ExcInternalError());
15136
15137 if ((!is_result_matrix_store_tril_only) ||
15138 (is_result_matrix_store_tril_only &&
15139 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
15140 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
15141 {
15147 std::unique_lock<std::mutex> ul(M0.update_lock, std::defer_lock);
15148 if (&M0 == &M)
15149 {
15150 ul.lock();
15151
15152#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 3
15153 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
15154 *M.col_index_range,
15155 *(Z.rkmatrix),
15156 *(Z.row_index_range),
15157 *(Z.col_index_range),
15158 fixed_rank);
15159#endif
15160
15161#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 1
15162 tbb::task_arena ta{ARENA_MAX_CONCURRENCY_IN_LU_AND_CHOL};
15163 ta.execute([&M, &Z, fixed_rank] {
15164 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
15165 *M.col_index_range,
15166 *(Z.rkmatrix),
15167 *(Z.row_index_range),
15168 *(Z.col_index_range),
15169 fixed_rank);
15170 });
15171#endif
15172
15173#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 2
15178 tbb::this_task_arena::isolate([&M, &Z, fixed_rank] {
15179 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
15180 *M.col_index_range,
15181 *(Z.rkmatrix),
15182 *(Z.row_index_range),
15183 *(Z.col_index_range),
15184 fixed_rank);
15185 });
15186#endif
15187 }
15188 else
15189 {
15190 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
15191 *M.col_index_range,
15192 *(Z.rkmatrix),
15193 *(Z.row_index_range),
15194 *(Z.col_index_range),
15195 fixed_rank);
15196 }
15197 }
15198 }
15199}
15200
15201
15217template <int spacedim, typename Number>
15218void
15224 const HMatrixSupport::BlockType block_type_for_local_Z,
15225 const unsigned int fixed_rank,
15226 const bool is_result_matrix_store_tril_only = false)
15227{
15232 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
15233
15234 if (is_result_matrix_store_tril_only)
15235 {
15236 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
15237 M0.get_property() ==
15238 HMatrixSupport::Property::hermite_symmetric ||
15239 M0.get_property() == HMatrixSupport::Property::lower_triangular,
15240 ExcInvalidHMatrixProperty(M0.get_property()));
15241 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
15242 ExcInvalidHMatrixBlockType(M0.get_block_type()));
15243 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
15244 M.get_property() ==
15245 HMatrixSupport::Property::hermite_symmetric ||
15246 M.get_property() == HMatrixSupport::Property::lower_triangular,
15247 ExcInvalidHMatrixProperty(M.get_property()));
15248 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
15249 ExcInvalidHMatrixBlockType(M.get_block_type()));
15250 }
15251
15252 // Array of empty child pointers used for initializing a block
15253 // cluster tree node.
15254 const std::array<
15255 typename BlockClusterTree<
15256 spacedim,
15257 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
15259 spacedim,
15260 typename numbers::NumberTraits<Number>::real_type>::child_num>
15261 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
15262
15272 typename BlockClusterTree<spacedim,
15273 typename numbers::NumberTraits<Number>::real_type>::
15274 node_value_type current_product_bc_node(
15275 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
15276 M1.bc_node->get_data_reference().get_sigma_node(),
15277 M2.bc_node->get_data_reference().get_sigma_node()),
15278 0,
15279 empty_child_pointers,
15280 nullptr,
15281 UnsplitMode);
15282
15288 if (M0.bc_node->get_data_reference().get_is_near_field())
15289 {
15290 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
15291
15292 current_product_bc_node.get_data_reference().set_is_near_field(true);
15293 }
15294 else
15295 {
15296 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
15297
15298 current_product_bc_node.get_data_reference().set_is_near_field(false);
15299 }
15300
15308 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
15309 bool is_result_matrix_Z_store_tril_only = false;
15310
15311 if (is_result_matrix_store_tril_only &&
15313 {
15318 Z_property = M.property;
15319 is_result_matrix_Z_store_tril_only = true;
15320
15326 Assert(block_type_for_local_Z ==
15327 HMatrixSupport::BlockType::diagonal_block,
15328 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
15329 }
15330
15336 HMatrix<spacedim, Number> Z(&current_product_bc_node,
15337 fixed_rank,
15338 Z_property,
15339 block_type_for_local_Z);
15340 // Local variable storing the rank-k matrix obtained from multiplication
15341 // involving leaf node.
15343 // Local variable storing the full matrix obtained from multiplication
15344 // involving leaf node.
15346 // The result matrix type for the multiplication involving leaf node.
15347 HMatrixType result_matrix_type = UndefinedMatrixType;
15348
15349 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
15350 {
15355 if (M1.type == RkMatrixType)
15356 {
15357 rk_h_Tmmult(*(M1.rkmatrix), M2, ZR);
15358 result_matrix_type = RkMatrixType;
15359 }
15360 else if (M2.type == RkMatrixType)
15361 {
15362 h_rk_Tmmult(M1, *(M2.rkmatrix), ZR);
15363 result_matrix_type = RkMatrixType;
15364 }
15365 else if (M1.type == FullMatrixType)
15366 {
15367 f_h_Tmmult(*(M1.fullmatrix), M2, ZF);
15368 result_matrix_type = FullMatrixType;
15369 }
15370 else if (M2.type == FullMatrixType)
15371 {
15372 h_f_Tmmult(M1, *(M2.fullmatrix), ZF);
15373 result_matrix_type = FullMatrixType;
15374 }
15375 else
15376 {
15377 Assert(false, ExcInternalError());
15378 result_matrix_type = UndefinedMatrixType;
15379 }
15380
15381 if (Z.type == RkMatrixType)
15382 {
15383 // The desired result should be a rank-k matrix.
15384 if (result_matrix_type == RkMatrixType)
15385 {
15386 *(Z.rkmatrix) = ZR;
15387 }
15388 else if (result_matrix_type == FullMatrixType)
15389 {
15390 // Convert the full matrix to rank-k matrix.
15391 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
15392 }
15393 else
15394 {
15395 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
15396 }
15397 }
15398 else if (Z.type == FullMatrixType)
15399 {
15400 // The desired result should be a full matrix.
15401 if (result_matrix_type == RkMatrixType)
15402 {
15403 // Convert the rank-k matrix to full matrix.
15405 }
15406 else if (result_matrix_type == FullMatrixType)
15407 {
15408 *(Z.fullmatrix) = ZF;
15409 }
15410 else
15411 {
15412 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
15413 }
15414
15422 if (is_result_matrix_Z_store_tril_only)
15423 {
15424 switch (Z.property)
15425 {
15426 case HMatrixSupport::Property::symmetric: {
15427 Z.fullmatrix->set_property(
15428 LAPACKSupport::Property::symmetric);
15429
15430 break;
15431 }
15432 case HMatrixSupport::Property::hermite_symmetric: {
15433 Z.fullmatrix->set_property(
15434 LAPACKSupport::Property::hermite_symmetric);
15435
15436 break;
15437 }
15438 case HMatrixSupport::Property::lower_triangular: {
15439 Z.fullmatrix->set_property(
15440 LAPACKSupport::Property::lower_triangular);
15441
15442 break;
15443 }
15444 default: {
15445 Assert(false, ExcInvalidHMatrixProperty(Z.property));
15446
15447 break;
15448 }
15449 }
15450 }
15451 }
15452 else
15453 {
15454 Assert(false, ExcInvalidHMatrixType(Z.type));
15455 }
15456 }
15457 else
15458 {
15467 const unsigned int local_fixed_rank =
15468 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
15469
15470 std::array<HMatrixSupport::BlockType,
15471 BlockClusterTree<spacedim,
15472 typename numbers::NumberTraits<
15473 Number>::real_type>::child_num>
15474 block_types_for_submatrices_of_local_Z;
15475 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
15476 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
15477
15479 Z,
15480 *(M1.submatrices[0]),
15481 *(M2.submatrices[0]),
15482 block_types_for_submatrices_of_local_Z[0],
15483 local_fixed_rank,
15484 is_result_matrix_Z_store_tril_only);
15486 Z,
15487 *(M1.submatrices[2]),
15488 *(M2.submatrices[2]),
15489 block_types_for_submatrices_of_local_Z[0],
15490 local_fixed_rank,
15491 is_result_matrix_Z_store_tril_only);
15492
15493 if ((!is_result_matrix_Z_store_tril_only) ||
15494 (is_result_matrix_Z_store_tril_only &&
15495 Z.property != HMatrixSupport::Property::symmetric &&
15496 Z.property != HMatrixSupport::Property::hermite_symmetric &&
15497 Z.property != HMatrixSupport::Property::lower_triangular))
15498 {
15510 Z,
15511 *(M1.submatrices[0]),
15512 *(M2.submatrices[1]),
15513 block_types_for_submatrices_of_local_Z[1],
15514 local_fixed_rank,
15515 is_result_matrix_Z_store_tril_only);
15517 Z,
15518 *(M1.submatrices[2]),
15519 *(M2.submatrices[3]),
15520 block_types_for_submatrices_of_local_Z[1],
15521 local_fixed_rank,
15522 is_result_matrix_Z_store_tril_only);
15523 }
15524
15526 Z,
15527 *(M1.submatrices[1]),
15528 *(M2.submatrices[0]),
15529 block_types_for_submatrices_of_local_Z[2],
15530 local_fixed_rank,
15531 is_result_matrix_Z_store_tril_only);
15533 Z,
15534 *(M1.submatrices[3]),
15535 *(M2.submatrices[2]),
15536 block_types_for_submatrices_of_local_Z[2],
15537 local_fixed_rank,
15538 is_result_matrix_Z_store_tril_only);
15539
15541 Z,
15542 *(M1.submatrices[1]),
15543 *(M2.submatrices[1]),
15544 block_types_for_submatrices_of_local_Z[3],
15545 local_fixed_rank,
15546 is_result_matrix_Z_store_tril_only);
15548 Z,
15549 *(M1.submatrices[3]),
15550 *(M2.submatrices[3]),
15551 block_types_for_submatrices_of_local_Z[3],
15552 local_fixed_rank,
15553 is_result_matrix_Z_store_tril_only);
15554 }
15555
15559 if (M0.bc_node->get_data_reference().get_is_near_field())
15560 {
15565 Assert(M.fullmatrix, ExcInternalError());
15566
15567 if ((!is_result_matrix_store_tril_only) ||
15568 (is_result_matrix_store_tril_only &&
15569 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
15570 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
15571 {
15572 M.fullmatrix->fill(*(Z.fullmatrix),
15573 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
15574 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
15575 0,
15576 0,
15577 Number(1.0),
15578 false,
15579 true);
15580 }
15581 }
15582 else
15583 {
15590 Assert(M.rkmatrix, ExcInternalError());
15591
15592 if ((!is_result_matrix_store_tril_only) ||
15593 (is_result_matrix_store_tril_only &&
15594 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
15595 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
15596 {
15597 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
15598 *M.col_index_range,
15599 *(Z.rkmatrix),
15600 *(Z.row_index_range),
15601 *(Z.col_index_range),
15602 fixed_rank);
15603 }
15604 }
15605}
15606
15607
15624template <int spacedim, typename Number>
15625void
15629 const Number alpha,
15632 const HMatrixSupport::BlockType block_type_for_local_Z,
15633 const unsigned int fixed_rank,
15634 const bool is_result_matrix_store_tril_only = false)
15635{
15640 Assert(M0.bc_node->is_leaf(), ExcMessage("M0 should be a leaf node!"));
15641
15642 if (is_result_matrix_store_tril_only)
15643 {
15644 Assert(M0.get_property() == HMatrixSupport::Property::symmetric ||
15645 M0.get_property() ==
15646 HMatrixSupport::Property::hermite_symmetric ||
15647 M0.get_property() == HMatrixSupport::Property::lower_triangular,
15648 ExcInvalidHMatrixProperty(M0.get_property()));
15649 Assert(M0.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
15650 ExcInvalidHMatrixBlockType(M0.get_block_type()));
15651 Assert(M.get_property() == HMatrixSupport::Property::symmetric ||
15652 M.get_property() ==
15653 HMatrixSupport::Property::hermite_symmetric ||
15654 M.get_property() == HMatrixSupport::Property::lower_triangular,
15655 ExcInvalidHMatrixProperty(M.get_property()));
15656 Assert(M.get_block_type() == HMatrixSupport::BlockType::diagonal_block,
15657 ExcInvalidHMatrixBlockType(M.get_block_type()));
15658 }
15659
15660 // Array of empty child pointers used for initializing a block
15661 // cluster tree node.
15662 const std::array<
15663 typename BlockClusterTree<
15664 spacedim,
15665 typename numbers::NumberTraits<Number>::real_type>::node_pointer_type,
15667 spacedim,
15668 typename numbers::NumberTraits<Number>::real_type>::child_num>
15669 empty_child_pointers{{nullptr, nullptr, nullptr, nullptr}};
15670
15680 typename BlockClusterTree<spacedim,
15681 typename numbers::NumberTraits<Number>::real_type>::
15682 node_value_type current_product_bc_node(
15683 BlockCluster<spacedim, typename numbers::NumberTraits<Number>::real_type>(
15684 M1.bc_node->get_data_reference().get_sigma_node(),
15685 M2.bc_node->get_data_reference().get_sigma_node()),
15686 0,
15687 empty_child_pointers,
15688 nullptr,
15689 UnsplitMode);
15690
15696 if (M0.bc_node->get_data_reference().get_is_near_field())
15697 {
15698 Assert(M0.type == FullMatrixType, ExcInvalidHMatrixType(M0.type));
15699
15700 current_product_bc_node.get_data_reference().set_is_near_field(true);
15701 }
15702 else
15703 {
15704 Assert(M0.type == RkMatrixType, ExcInvalidHMatrixType(M0.type));
15705
15706 current_product_bc_node.get_data_reference().set_is_near_field(false);
15707 }
15708
15716 HMatrixSupport::Property Z_property = HMatrixSupport::Property::general;
15717 bool is_result_matrix_Z_store_tril_only = false;
15718
15719 if (is_result_matrix_store_tril_only &&
15721 {
15726 Z_property = M.property;
15727 is_result_matrix_Z_store_tril_only = true;
15728
15734 Assert(block_type_for_local_Z ==
15735 HMatrixSupport::BlockType::diagonal_block,
15736 ExcInvalidHMatrixBlockType(block_type_for_local_Z));
15737 }
15738
15744 HMatrix<spacedim, Number> Z(&current_product_bc_node,
15745 fixed_rank,
15746 Z_property,
15747 block_type_for_local_Z);
15748 // Local variable storing the rank-k matrix obtained from multiplication
15749 // involving leaf node.
15751 // Local variable storing the full matrix obtained from multiplication
15752 // involving leaf node.
15754 // The result matrix type for the multiplication involving leaf node.
15755 HMatrixType result_matrix_type = UndefinedMatrixType;
15756
15757 if (M1.bc_node->is_leaf() || M2.bc_node->is_leaf())
15758 {
15763 if (M1.type == RkMatrixType)
15764 {
15765 rk_h_Tmmult(alpha, *(M1.rkmatrix), M2, ZR);
15766 result_matrix_type = RkMatrixType;
15767 }
15768 else if (M2.type == RkMatrixType)
15769 {
15770 h_rk_Tmmult(alpha, M1, *(M2.rkmatrix), ZR);
15771 result_matrix_type = RkMatrixType;
15772 }
15773 else if (M1.type == FullMatrixType)
15774 {
15775 f_h_Tmmult(alpha, *(M1.fullmatrix), M2, ZF);
15776 result_matrix_type = FullMatrixType;
15777 }
15778 else if (M2.type == FullMatrixType)
15779 {
15780 h_f_Tmmult(alpha, M1, *(M2.fullmatrix), ZF);
15781 result_matrix_type = FullMatrixType;
15782 }
15783 else
15784 {
15785 Assert(false, ExcInternalError());
15786 result_matrix_type = UndefinedMatrixType;
15787 }
15788
15789 if (Z.type == RkMatrixType)
15790 {
15791 // The desired result should be a rank-k matrix.
15792 if (result_matrix_type == RkMatrixType)
15793 {
15794 *(Z.rkmatrix) = ZR;
15795 }
15796 else if (result_matrix_type == FullMatrixType)
15797 {
15798 // Convert the full matrix to rank-k matrix.
15799 *(Z.rkmatrix) = RkMatrix<Number>(fixed_rank, ZF);
15800 }
15801 else
15802 {
15803 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
15804 }
15805 }
15806 else if (Z.type == FullMatrixType)
15807 {
15808 // The desired result should be a full matrix.
15809 if (result_matrix_type == RkMatrixType)
15810 {
15811 // Convert the rank-k matrix to full matrix.
15813 }
15814 else if (result_matrix_type == FullMatrixType)
15815 {
15816 *(Z.fullmatrix) = ZF;
15817 }
15818 else
15819 {
15820 Assert(false, ExcInvalidHMatrixType(result_matrix_type));
15821 }
15822
15830 if (is_result_matrix_Z_store_tril_only)
15831 {
15832 switch (Z.property)
15833 {
15834 case HMatrixSupport::Property::symmetric: {
15835 Z.fullmatrix->set_property(
15836 LAPACKSupport::Property::symmetric);
15837
15838 break;
15839 }
15840 case HMatrixSupport::Property::hermite_symmetric: {
15841 Z.fullmatrix->set_property(
15842 LAPACKSupport::Property::hermite_symmetric);
15843
15844 break;
15845 }
15846 case HMatrixSupport::Property::lower_triangular: {
15847 Z.fullmatrix->set_property(
15848 LAPACKSupport::Property::lower_triangular);
15849
15850 break;
15851 }
15852 default: {
15853 Assert(false, ExcInvalidHMatrixProperty(Z.property));
15854
15855 break;
15856 }
15857 }
15858 }
15859 }
15860 else
15861 {
15862 Assert(false, ExcInvalidHMatrixType(Z.type));
15863 }
15864 }
15865 else
15866 {
15875 const unsigned int local_fixed_rank =
15876 std::min(fixed_rank * 2, std::min(Z.m, Z.n));
15877
15878 std::array<HMatrixSupport::BlockType,
15879 BlockClusterTree<spacedim,
15880 typename numbers::NumberTraits<
15881 Number>::real_type>::child_num>
15882 block_types_for_submatrices_of_local_Z;
15883 HMatrixSupport::infer_submatrix_block_types_from_parent_hmat(
15884 block_type_for_local_Z, block_types_for_submatrices_of_local_Z);
15885
15887 Z,
15888 alpha,
15889 *(M1.submatrices[0]),
15890 *(M2.submatrices[0]),
15891 block_types_for_submatrices_of_local_Z[0],
15892 local_fixed_rank,
15893 is_result_matrix_Z_store_tril_only);
15895 Z,
15896 alpha,
15897 *(M1.submatrices[2]),
15898 *(M2.submatrices[2]),
15899 block_types_for_submatrices_of_local_Z[0],
15900 local_fixed_rank,
15901 is_result_matrix_Z_store_tril_only);
15902
15903 if ((!is_result_matrix_Z_store_tril_only) ||
15904 (is_result_matrix_Z_store_tril_only &&
15905 Z.property != HMatrixSupport::Property::symmetric &&
15906 Z.property != HMatrixSupport::Property::hermite_symmetric &&
15907 Z.property != HMatrixSupport::Property::lower_triangular))
15908 {
15920 Z,
15921 alpha,
15922 *(M1.submatrices[0]),
15923 *(M2.submatrices[1]),
15924 block_types_for_submatrices_of_local_Z[1],
15925 local_fixed_rank,
15926 is_result_matrix_Z_store_tril_only);
15928 Z,
15929 alpha,
15930 *(M1.submatrices[2]),
15931 *(M2.submatrices[3]),
15932 block_types_for_submatrices_of_local_Z[1],
15933 local_fixed_rank,
15934 is_result_matrix_Z_store_tril_only);
15935 }
15936
15938 Z,
15939 alpha,
15940 *(M1.submatrices[1]),
15941 *(M2.submatrices[0]),
15942 block_types_for_submatrices_of_local_Z[2],
15943 local_fixed_rank,
15944 is_result_matrix_Z_store_tril_only);
15946 Z,
15947 alpha,
15948 *(M1.submatrices[3]),
15949 *(M2.submatrices[2]),
15950 block_types_for_submatrices_of_local_Z[2],
15951 local_fixed_rank,
15952 is_result_matrix_Z_store_tril_only);
15953
15955 Z,
15956 alpha,
15957 *(M1.submatrices[1]),
15958 *(M2.submatrices[1]),
15959 block_types_for_submatrices_of_local_Z[3],
15960 local_fixed_rank,
15961 is_result_matrix_Z_store_tril_only);
15963 Z,
15964 alpha,
15965 *(M1.submatrices[3]),
15966 *(M2.submatrices[3]),
15967 block_types_for_submatrices_of_local_Z[3],
15968 local_fixed_rank,
15969 is_result_matrix_Z_store_tril_only);
15970 }
15971
15975 if (M0.bc_node->get_data_reference().get_is_near_field())
15976 {
15981 Assert(M.fullmatrix, ExcInternalError());
15982
15983 if ((!is_result_matrix_store_tril_only) ||
15984 (is_result_matrix_store_tril_only &&
15985 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
15986 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
15987 {
15988 M.fullmatrix->fill(*(Z.fullmatrix),
15989 (*Z.row_index_range)[0] - (*M.row_index_range)[0],
15990 (*Z.col_index_range)[0] - (*M.col_index_range)[0],
15991 0,
15992 0,
15993 Number(1.0),
15994 false,
15995 true);
15996 }
15997 }
15998 else
15999 {
16006 Assert(M.rkmatrix, ExcInternalError());
16007
16008 if ((!is_result_matrix_store_tril_only) ||
16009 (is_result_matrix_store_tril_only &&
16010 M.block_type != HMatrixSupport::BlockType::upper_triangular_block &&
16011 Z.block_type != HMatrixSupport::BlockType::upper_triangular_block))
16012 {
16013 M.rkmatrix->assemble_from_rkmatrix(*M.row_index_range,
16014 *M.col_index_range,
16015 *(Z.rkmatrix),
16016 *(Z.row_index_range),
16017 *(Z.col_index_range),
16018 fixed_rank);
16019 }
16020 }
16021}
16022
16023
16037template <int spacedim, typename Number>
16038void
16042 const unsigned int fixed_rank,
16043 const bool is_result_matrix_store_tril_only = false)
16044{
16045 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
16046 !(M.bc_node->is_leaf()))
16047 {
16053 *(M1.submatrices[0]),
16054 *(M2.submatrices[0]),
16055 fixed_rank,
16056 is_result_matrix_store_tril_only);
16058 *(M1.submatrices[1]),
16059 *(M2.submatrices[2]),
16060 fixed_rank,
16061 is_result_matrix_store_tril_only);
16062
16068 if ((!is_result_matrix_store_tril_only) ||
16069 (is_result_matrix_store_tril_only &&
16070 M.property != HMatrixSupport::Property::symmetric &&
16071 M.property != HMatrixSupport::Property::hermite_symmetric &&
16072 M.property != HMatrixSupport::Property::lower_triangular))
16073 {
16084 *(M1.submatrices[0]),
16085 *(M2.submatrices[1]),
16086 fixed_rank,
16087 false);
16089 *(M1.submatrices[1]),
16090 *(M2.submatrices[3]),
16091 fixed_rank,
16092 false);
16093 }
16094
16096 *(M1.submatrices[2]),
16097 *(M2.submatrices[0]),
16098 fixed_rank,
16099 false);
16101 *(M1.submatrices[3]),
16102 *(M2.submatrices[2]),
16103 fixed_rank,
16104 false);
16105
16107 *(M1.submatrices[2]),
16108 *(M2.submatrices[1]),
16109 fixed_rank,
16110 is_result_matrix_store_tril_only);
16112 *(M1.submatrices[3]),
16113 *(M2.submatrices[3]),
16114 fixed_rank,
16115 is_result_matrix_store_tril_only);
16116 }
16117 else if (!(M.bc_node->is_leaf()))
16118 {
16134 if (M1.type == RkMatrixType)
16135 {
16136 rk_h_mmult(*(M1.rkmatrix), M2, Z);
16137 }
16138 else if (M2.type == RkMatrixType)
16139 {
16140 h_rk_mmult(M1, *(M2.rkmatrix), Z);
16141 }
16142 else if (M1.type == FullMatrixType)
16143 {
16144 f_h_mmult(*(M1.fullmatrix), M2, Z);
16145 }
16146 else if (M2.type == FullMatrixType)
16147 {
16148 h_f_mmult(M1, *(M2.fullmatrix), Z);
16149 }
16150 else
16151 {
16152 Assert(false, ExcInternalError());
16153 }
16154
16169 M.add(Z, fixed_rank, is_result_matrix_store_tril_only);
16170 }
16171 else
16172 {
16181 M,
16182 M1,
16183 M2,
16184 M.block_type,
16185 fixed_rank,
16186 is_result_matrix_store_tril_only);
16187 }
16188}
16189
16190
16208template <int spacedim, typename Number>
16209void
16211 const Number alpha,
16214 const unsigned int fixed_rank,
16215 const bool is_result_matrix_store_tril_only = false)
16216{
16217 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
16218 !(M.bc_node->is_leaf()))
16219 {
16225 alpha,
16226 *(M1.submatrices[0]),
16227 *(M2.submatrices[0]),
16228 fixed_rank,
16229 is_result_matrix_store_tril_only);
16231 alpha,
16232 *(M1.submatrices[1]),
16233 *(M2.submatrices[2]),
16234 fixed_rank,
16235 is_result_matrix_store_tril_only);
16236
16241 if ((!is_result_matrix_store_tril_only) ||
16242 (is_result_matrix_store_tril_only &&
16243 M.property != HMatrixSupport::Property::symmetric &&
16244 M.property != HMatrixSupport::Property::hermite_symmetric &&
16245 M.property != HMatrixSupport::Property::lower_triangular))
16246 {
16257 alpha,
16258 *(M1.submatrices[0]),
16259 *(M2.submatrices[1]),
16260 fixed_rank,
16261 false);
16263 alpha,
16264 *(M1.submatrices[1]),
16265 *(M2.submatrices[3]),
16266 fixed_rank,
16267 false);
16268 }
16269
16271 alpha,
16272 *(M1.submatrices[2]),
16273 *(M2.submatrices[0]),
16274 fixed_rank,
16275 false);
16277 alpha,
16278 *(M1.submatrices[3]),
16279 *(M2.submatrices[2]),
16280 fixed_rank,
16281 false);
16282
16284 alpha,
16285 *(M1.submatrices[2]),
16286 *(M2.submatrices[1]),
16287 fixed_rank,
16288 is_result_matrix_store_tril_only);
16290 alpha,
16291 *(M1.submatrices[3]),
16292 *(M2.submatrices[3]),
16293 fixed_rank,
16294 is_result_matrix_store_tril_only);
16295 }
16296 else if (!(M.bc_node->is_leaf()))
16297 {
16313 if (M1.type == RkMatrixType)
16314 {
16315 rk_h_mmult(alpha, *(M1.rkmatrix), M2, Z);
16316 }
16317 else if (M2.type == RkMatrixType)
16318 {
16319 h_rk_mmult(alpha, M1, *(M2.rkmatrix), Z);
16320 }
16321 else if (M1.type == FullMatrixType)
16322 {
16323 f_h_mmult(alpha, *(M1.fullmatrix), M2, Z);
16324 }
16325 else if (M2.type == FullMatrixType)
16326 {
16327 h_f_mmult(alpha, M1, *(M2.fullmatrix), Z);
16328 }
16329 else
16330 {
16331 Assert(false, ExcInternalError());
16332 }
16333
16348 M.add(Z, fixed_rank, is_result_matrix_store_tril_only);
16349 }
16350 else
16351 {
16360 M,
16361 alpha,
16362 M1,
16363 M2,
16364 M.block_type,
16365 fixed_rank,
16366 is_result_matrix_store_tril_only);
16367 }
16368}
16369
16370
16371template <int spacedim, typename Number>
16372void
16375 const Number alpha,
16378 const unsigned int fixed_rank,
16379 const bool is_result_matrix_store_tril_only = false)
16380{
16381 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
16382 !(M.bc_node->is_leaf()))
16383 {
16389 *(M.submatrices[0]),
16390 alpha,
16391 *(M1.submatrices[0]),
16392 *(M2.submatrices[0]),
16393 fixed_rank,
16394 is_result_matrix_store_tril_only);
16396 *(M.submatrices[0]),
16397 alpha,
16398 *(M1.submatrices[1]),
16399 *(M2.submatrices[2]),
16400 fixed_rank,
16401 is_result_matrix_store_tril_only);
16402
16407 if ((!is_result_matrix_store_tril_only) ||
16408 (is_result_matrix_store_tril_only &&
16409 M.property != HMatrixSupport::Property::symmetric &&
16410 M.property != HMatrixSupport::Property::hermite_symmetric &&
16411 M.property != HMatrixSupport::Property::lower_triangular))
16412 {
16423 alpha,
16424 *(M1.submatrices[0]),
16425 *(M2.submatrices[1]),
16426 fixed_rank,
16427 false);
16429 alpha,
16430 *(M1.submatrices[1]),
16431 *(M2.submatrices[3]),
16432 fixed_rank,
16433 false);
16434 }
16435
16437 alpha,
16438 *(M1.submatrices[2]),
16439 *(M2.submatrices[0]),
16440 fixed_rank,
16441 false);
16443 alpha,
16444 *(M1.submatrices[3]),
16445 *(M2.submatrices[2]),
16446 fixed_rank,
16447 false);
16448
16450 *(M.submatrices[3]),
16451 alpha,
16452 *(M1.submatrices[2]),
16453 *(M2.submatrices[1]),
16454 fixed_rank,
16455 is_result_matrix_store_tril_only);
16457 *(M.submatrices[3]),
16458 alpha,
16459 *(M1.submatrices[3]),
16460 *(M2.submatrices[3]),
16461 fixed_rank,
16462 is_result_matrix_store_tril_only);
16463 }
16464 else if (!(M.bc_node->is_leaf()))
16465 {
16481 if (M1.type == RkMatrixType)
16482 {
16483 rk_h_mmult(alpha, *(M1.rkmatrix), M2, Z);
16484 }
16485 else if (M2.type == RkMatrixType)
16486 {
16487 h_rk_mmult(alpha, M1, *(M2.rkmatrix), Z);
16488 }
16489 else if (M1.type == FullMatrixType)
16490 {
16491 f_h_mmult(alpha, *(M1.fullmatrix), M2, Z);
16492 }
16493 else if (M2.type == FullMatrixType)
16494 {
16495 h_f_mmult(alpha, M1, *(M2.fullmatrix), Z);
16496 }
16497 else
16498 {
16499 Assert(false, ExcInternalError());
16500 }
16501
16517 fixed_rank,
16518 is_result_matrix_store_tril_only);
16519 }
16520 else
16521 {
16530 M,
16531 M,
16532 alpha,
16533 M1,
16534 M2,
16535 M.block_type,
16536 fixed_rank,
16537 is_result_matrix_store_tril_only);
16538 }
16539}
16540
16541
16556template <int spacedim, typename Number>
16557void
16561 const unsigned int fixed_rank,
16562 const bool is_result_matrix_store_tril_only = false)
16563{
16564 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
16565 !(M.bc_node->is_leaf()))
16566 {
16572 *(M1.submatrices[0]),
16573 *(M2.submatrices[0]),
16574 fixed_rank,
16575 is_result_matrix_store_tril_only);
16577 *(M1.submatrices[1]),
16578 *(M2.submatrices[1]),
16579 fixed_rank,
16580 is_result_matrix_store_tril_only);
16581
16586 if ((!is_result_matrix_store_tril_only) ||
16587 (is_result_matrix_store_tril_only &&
16588 M.property != HMatrixSupport::Property::symmetric &&
16589 M.property != HMatrixSupport::Property::hermite_symmetric &&
16590 M.property != HMatrixSupport::Property::lower_triangular))
16591 {
16602 *(M1.submatrices[0]),
16603 *(M2.submatrices[2]),
16604 fixed_rank,
16605 false);
16607 *(M1.submatrices[1]),
16608 *(M2.submatrices[3]),
16609 fixed_rank,
16610 false);
16611 }
16612
16614 *(M1.submatrices[2]),
16615 *(M2.submatrices[0]),
16616 fixed_rank,
16617 false);
16619 *(M1.submatrices[3]),
16620 *(M2.submatrices[1]),
16621 fixed_rank,
16622 false);
16623
16625 *(M1.submatrices[2]),
16626 *(M2.submatrices[2]),
16627 fixed_rank,
16628 is_result_matrix_store_tril_only);
16630 *(M1.submatrices[3]),
16631 *(M2.submatrices[3]),
16632 fixed_rank,
16633 is_result_matrix_store_tril_only);
16634 }
16635 else if (!(M.bc_node->is_leaf()))
16636 {
16651 if (M1.type == RkMatrixType)
16652 {
16653 rk_h_mTmult(*(M1.rkmatrix), M2, Z);
16654 }
16655 else if (M2.type == RkMatrixType)
16656 {
16657 h_rk_mTmult(M1, *(M2.rkmatrix), Z);
16658 }
16659 else if (M1.type == FullMatrixType)
16660 {
16661 f_h_mTmult(*(M1.fullmatrix), M2, Z);
16662 }
16663 else if (M2.type == FullMatrixType)
16664 {
16665 h_f_mTmult(M1, *(M2.fullmatrix), Z);
16666 }
16667 else
16668 {
16669 Assert(false, ExcInternalError());
16670 }
16671
16686 M.add(Z, fixed_rank, is_result_matrix_store_tril_only);
16687 }
16688 else
16689 {
16698 M,
16699 M1,
16700 M2,
16701 M.block_type,
16702 fixed_rank,
16703 is_result_matrix_store_tril_only);
16704 }
16705}
16706
16707
16723template <int spacedim, typename Number>
16724void
16726 const Number alpha,
16729 const unsigned int fixed_rank,
16730 const bool is_result_matrix_store_tril_only = false)
16731{
16732 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
16733 !(M.bc_node->is_leaf()))
16734 {
16740 alpha,
16741 *(M1.submatrices[0]),
16742 *(M2.submatrices[0]),
16743 fixed_rank,
16744 is_result_matrix_store_tril_only);
16746 alpha,
16747 *(M1.submatrices[1]),
16748 *(M2.submatrices[1]),
16749 fixed_rank,
16750 is_result_matrix_store_tril_only);
16751
16756 if ((!is_result_matrix_store_tril_only) ||
16757 (is_result_matrix_store_tril_only &&
16758 M.property != HMatrixSupport::Property::symmetric &&
16759 M.property != HMatrixSupport::Property::hermite_symmetric &&
16760 M.property != HMatrixSupport::Property::lower_triangular))
16761 {
16772 alpha,
16773 *(M1.submatrices[0]),
16774 *(M2.submatrices[2]),
16775 fixed_rank,
16776 false);
16778 alpha,
16779 *(M1.submatrices[1]),
16780 *(M2.submatrices[3]),
16781 fixed_rank,
16782 false);
16783 }
16784
16786 alpha,
16787 *(M1.submatrices[2]),
16788 *(M2.submatrices[0]),
16789 fixed_rank,
16790 false);
16792 alpha,
16793 *(M1.submatrices[3]),
16794 *(M2.submatrices[1]),
16795 fixed_rank,
16796 false);
16797
16799 alpha,
16800 *(M1.submatrices[2]),
16801 *(M2.submatrices[2]),
16802 fixed_rank,
16803 is_result_matrix_store_tril_only);
16805 alpha,
16806 *(M1.submatrices[3]),
16807 *(M2.submatrices[3]),
16808 fixed_rank,
16809 is_result_matrix_store_tril_only);
16810 }
16811 else if (!(M.bc_node->is_leaf()))
16812 {
16827 if (M1.type == RkMatrixType)
16828 {
16829 rk_h_mTmult(alpha, *(M1.rkmatrix), M2, Z);
16830 }
16831 else if (M2.type == RkMatrixType)
16832 {
16833 h_rk_mTmult(alpha, M1, *(M2.rkmatrix), Z);
16834 }
16835 else if (M1.type == FullMatrixType)
16836 {
16837 f_h_mTmult(alpha, *(M1.fullmatrix), M2, Z);
16838 }
16839 else if (M2.type == FullMatrixType)
16840 {
16841 h_f_mTmult(alpha, M1, *(M2.fullmatrix), Z);
16842 }
16843 else
16844 {
16845 Assert(false, ExcInternalError());
16846 }
16847
16862 M.add(Z, fixed_rank, is_result_matrix_store_tril_only);
16863 }
16864 else
16865 {
16874 M,
16875 alpha,
16876 M1,
16877 M2,
16878 M.block_type,
16879 fixed_rank,
16880 is_result_matrix_store_tril_only);
16881 }
16882}
16883
16884
16885template <int spacedim, typename Number>
16886void
16889 const Number alpha,
16892 const unsigned int fixed_rank,
16893 const bool is_result_matrix_store_tril_only = false)
16894{
16895 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
16896 !(M.bc_node->is_leaf()))
16897 {
16903 *(M.submatrices[0]),
16904 alpha,
16905 *(M1.submatrices[0]),
16906 *(M2.submatrices[0]),
16907 fixed_rank,
16908 is_result_matrix_store_tril_only);
16910 *(M.submatrices[0]),
16911 alpha,
16912 *(M1.submatrices[1]),
16913 *(M2.submatrices[1]),
16914 fixed_rank,
16915 is_result_matrix_store_tril_only);
16916
16921 if ((!is_result_matrix_store_tril_only) ||
16922 (is_result_matrix_store_tril_only &&
16923 M.property != HMatrixSupport::Property::symmetric &&
16924 M.property != HMatrixSupport::Property::hermite_symmetric &&
16925 M.property != HMatrixSupport::Property::lower_triangular))
16926 {
16937 *(M.submatrices[1]),
16938 alpha,
16939 *(M1.submatrices[0]),
16940 *(M2.submatrices[2]),
16941 fixed_rank,
16942 false);
16944 *(M.submatrices[1]),
16945 alpha,
16946 *(M1.submatrices[1]),
16947 *(M2.submatrices[3]),
16948 fixed_rank,
16949 false);
16950 }
16951
16953 alpha,
16954 *(M1.submatrices[2]),
16955 *(M2.submatrices[0]),
16956 fixed_rank,
16957 false);
16959 alpha,
16960 *(M1.submatrices[3]),
16961 *(M2.submatrices[1]),
16962 fixed_rank,
16963 false);
16964
16966 *(M.submatrices[3]),
16967 alpha,
16968 *(M1.submatrices[2]),
16969 *(M2.submatrices[2]),
16970 fixed_rank,
16971 is_result_matrix_store_tril_only);
16973 *(M.submatrices[3]),
16974 alpha,
16975 *(M1.submatrices[3]),
16976 *(M2.submatrices[3]),
16977 fixed_rank,
16978 is_result_matrix_store_tril_only);
16979 }
16980 else if (!(M.bc_node->is_leaf()))
16981 {
16996 if (M1.type == RkMatrixType)
16997 {
16998 rk_h_mTmult(alpha, *(M1.rkmatrix), M2, Z);
16999 }
17000 else if (M2.type == RkMatrixType)
17001 {
17002 h_rk_mTmult(alpha, M1, *(M2.rkmatrix), Z);
17003 }
17004 else if (M1.type == FullMatrixType)
17005 {
17006 f_h_mTmult(alpha, *(M1.fullmatrix), M2, Z);
17007 }
17008 else if (M2.type == FullMatrixType)
17009 {
17010 h_f_mTmult(alpha, M1, *(M2.fullmatrix), Z);
17011 }
17012 else
17013 {
17014 Assert(false, ExcInternalError());
17015 }
17016
17032 fixed_rank,
17033 is_result_matrix_store_tril_only);
17034 }
17035 else
17036 {
17045 M,
17046 M,
17047 alpha,
17048 M1,
17049 M2,
17050 M.block_type,
17051 fixed_rank,
17052 is_result_matrix_store_tril_only);
17053 }
17054}
17055
17056
17071template <int spacedim, typename Number>
17072void
17076 const unsigned int fixed_rank,
17077 const bool is_result_matrix_store_tril_only = false)
17078{
17079 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
17080 !(M.bc_node->is_leaf()))
17081 {
17087 *(M1.submatrices[0]),
17088 *(M2.submatrices[0]),
17089 fixed_rank,
17090 is_result_matrix_store_tril_only);
17092 *(M1.submatrices[2]),
17093 *(M2.submatrices[2]),
17094 fixed_rank,
17095 is_result_matrix_store_tril_only);
17096
17101 if ((!is_result_matrix_store_tril_only) ||
17102 (is_result_matrix_store_tril_only &&
17103 M.property != HMatrixSupport::Property::symmetric &&
17104 M.property != HMatrixSupport::Property::hermite_symmetric &&
17105 M.property != HMatrixSupport::Property::lower_triangular))
17106 {
17117 *(M1.submatrices[0]),
17118 *(M2.submatrices[1]),
17119 fixed_rank,
17120 false);
17122 *(M1.submatrices[2]),
17123 *(M2.submatrices[3]),
17124 fixed_rank,
17125 false);
17126 }
17127
17129 *(M1.submatrices[1]),
17130 *(M2.submatrices[0]),
17131 fixed_rank,
17132 false);
17134 *(M1.submatrices[3]),
17135 *(M2.submatrices[2]),
17136 fixed_rank,
17137 false);
17138
17140 *(M1.submatrices[1]),
17141 *(M2.submatrices[1]),
17142 fixed_rank,
17143 is_result_matrix_store_tril_only);
17145 *(M1.submatrices[3]),
17146 *(M2.submatrices[3]),
17147 fixed_rank,
17148 is_result_matrix_store_tril_only);
17149 }
17150 else if (!(M.bc_node->is_leaf()))
17151 {
17167 if (M1.type == RkMatrixType)
17168 {
17169 rk_h_Tmmult(*(M1.rkmatrix), M2, Z);
17170 }
17171 else if (M2.type == RkMatrixType)
17172 {
17173 h_rk_Tmmult(M1, *(M2.rkmatrix), Z);
17174 }
17175 else if (M1.type == FullMatrixType)
17176 {
17177 f_h_Tmmult(*(M1.fullmatrix), M2, Z);
17178 }
17179 else if (M2.type == FullMatrixType)
17180 {
17181 h_f_Tmmult(M1, *(M2.fullmatrix), Z);
17182 }
17183 else
17184 {
17185 Assert(false, ExcInternalError());
17186 }
17187
17202 M.add(Z, fixed_rank, is_result_matrix_store_tril_only);
17203 }
17204 else
17205 {
17214 M,
17215 M1,
17216 M2,
17217 M.block_type,
17218 fixed_rank,
17219 is_result_matrix_store_tril_only);
17220 }
17221}
17222
17223
17239template <int spacedim, typename Number>
17240void
17242 const Number alpha,
17245 const unsigned int fixed_rank,
17246 const bool is_result_matrix_store_tril_only = false)
17247{
17248 if (!(M1.bc_node->is_leaf()) && !(M2.bc_node->is_leaf()) &&
17249 !(M.bc_node->is_leaf()))
17250 {
17256 alpha,
17257 *(M1.submatrices[0]),
17258 *(M2.submatrices[0]),
17259 fixed_rank,
17260 is_result_matrix_store_tril_only);
17262 alpha,
17263 *(M1.submatrices[2]),
17264 *(M2.submatrices[2]),
17265 fixed_rank,
17266 is_result_matrix_store_tril_only);
17267
17272 if ((!is_result_matrix_store_tril_only) ||
17273 (is_result_matrix_store_tril_only &&
17274 M.property != HMatrixSupport::Property::symmetric &&
17275 M.property != HMatrixSupport::Property::hermite_symmetric &&
17276 M.property != HMatrixSupport::Property::lower_triangular))
17277 {
17288 alpha,
17289 *(M1.submatrices[0]),
17290 *(M2.submatrices[1]),
17291 fixed_rank,
17292 false);
17294 alpha,
17295 *(M1.submatrices[2]),
17296 *(M2.submatrices[3]),
17297 fixed_rank,
17298 false);
17299 }
17300
17302 alpha,
17303 *(M1.submatrices[1]),
17304 *(M2.submatrices[0]),
17305 fixed_rank,
17306 false);
17308 alpha,
17309 *(M1.submatrices[3]),
17310 *(M2.submatrices[2]),
17311 fixed_rank,
17312 false);
17313
17315 alpha,
17316 *(M1.submatrices[1]),
17317 *(M2.submatrices[1]),
17318 fixed_rank,
17319 is_result_matrix_store_tril_only);
17321 alpha,
17322 *(M1.submatrices[3]),
17323 *(M2.submatrices[3]),
17324 fixed_rank,
17325 is_result_matrix_store_tril_only);
17326 }
17327 else if (!(M.bc_node->is_leaf()))
17328 {
17344 if (M1.type == RkMatrixType)
17345 {
17346 rk_h_Tmmult(alpha, *(M1.rkmatrix), M2, Z);
17347 }
17348 else if (M2.type == RkMatrixType)
17349 {
17350 h_rk_Tmmult(alpha, M1, *(M2.rkmatrix), Z);
17351 }
17352 else if (M1.type == FullMatrixType)
17353 {
17354 f_h_Tmmult(alpha, *(M1.fullmatrix), M2, Z);
17355 }
17356 else if (M2.type == FullMatrixType)
17357 {
17358 h_f_Tmmult(alpha, M1, *(M2.fullmatrix), Z);
17359 }
17360 else
17361 {
17362 Assert(false, ExcInternalError());
17363 }
17364
17379 M.add(Z, fixed_rank, is_result_matrix_store_tril_only);
17380 }
17381 else
17382 {
17391 M,
17392 alpha,
17393 M1,
17394 M2,
17395 M.block_type,
17396 fixed_rank,
17397 is_result_matrix_store_tril_only);
17398 }
17399}
17400
17401
17419template <int spacedim, typename Number = double>
17420void
17422 const HMatrix<spacedim, Number> &hmat_src)
17423{
17424 hmat_dst.type = hmat_src.type;
17425 hmat_dst.state = hmat_src.state;
17426 hmat_dst.property = hmat_src.property;
17427 hmat_dst.block_type = hmat_src.block_type;
17428 hmat_dst.submatrix_index = hmat_src.submatrix_index;
17429
17433 if (hmat_src.rkmatrix != nullptr)
17434 {
17435 hmat_dst.rkmatrix = new RkMatrix<Number>(*(hmat_src.rkmatrix));
17436 }
17437 else
17438 {
17439 hmat_dst.rkmatrix = nullptr;
17440 }
17441
17445 if (hmat_src.fullmatrix != nullptr)
17446 {
17447 hmat_dst.fullmatrix =
17448 new LAPACKFullMatrixExt<Number>(*(hmat_src.fullmatrix));
17449 }
17450 else
17451 {
17452 hmat_dst.fullmatrix = nullptr;
17453 }
17454
17455 hmat_dst.bc_node = hmat_src.bc_node;
17456 hmat_dst.row_index_range = hmat_src.row_index_range;
17457 hmat_dst.col_index_range = hmat_src.col_index_range;
17458 hmat_dst.m = hmat_src.m;
17459 hmat_dst.n = hmat_src.n;
17460}
17461
17462
17472template <int spacedim, typename Number = double>
17473void
17475 HMatrix<spacedim, Number> &&hmat_src)
17476{
17477 hmat_dst.type = hmat_src.type;
17478 hmat_dst.state = hmat_src.state;
17479 hmat_dst.property = hmat_src.property;
17480 hmat_dst.block_type = hmat_src.block_type;
17481 hmat_dst.dot_node_id = hmat_src.dot_node_id;
17482 hmat_dst.submatrices = hmat_src.submatrices;
17483 hmat_dst.submatrix_index = hmat_src.submatrix_index;
17484 hmat_dst.parent = hmat_src.parent;
17485 hmat_dst.next_same_level_hmat_node = hmat_src.next_same_level_hmat_node;
17487 hmat_src.next_same_level_same_row_hmat_node;
17489 hmat_src.next_same_level_same_column_hmat_node;
17491 hmat_src.previous_same_level_same_row_hmat_node;
17493 hmat_src.previous_same_level_same_column_hmat_node;
17494 hmat_dst.leaf_set = hmat_src.leaf_set;
17495 hmat_dst.near_field_leaf_set = hmat_src.near_field_leaf_set;
17496 hmat_dst.far_field_leaf_set = hmat_src.far_field_leaf_set;
17497 hmat_dst.rkmatrix = hmat_src.rkmatrix;
17498 hmat_dst.fullmatrix = hmat_src.fullmatrix;
17499 hmat_dst.bc_node = hmat_src.bc_node;
17500 hmat_dst.row_index_range = hmat_src.row_index_range;
17501 hmat_dst.col_index_range = hmat_src.col_index_range;
17502 hmat_dst.m = hmat_src.m;
17503 hmat_dst.n = hmat_src.n;
17504 hmat_dst.Sigma_P = hmat_src.Sigma_P;
17505 hmat_dst.Sigma_R = hmat_src.Sigma_R;
17506 hmat_dst.Sigma_F = hmat_src.Sigma_F;
17507 hmat_dst.Tind = std::move(hmat_src.Tind);
17508}
17509
17510
17516template <int spacedim, typename Number = double>
17517void
17519 const HMatrix<spacedim, Number> &hmat_src)
17520{
17524 copy_hmatrix_node(hmat_dst, hmat_src);
17525
17529 for (HMatrix<spacedim, Number> *submatrix : hmat_src.submatrices)
17530 {
17531 Assert(submatrix, ExcInternalError());
17532
17539 copy_hmatrix(*child_hmat, *submatrix);
17540 hmat_dst.submatrices.push_back(child_hmat);
17541 child_hmat->parent = &hmat_dst;
17542 }
17543}
17544
17545
17546template <int spacedim, typename Number = double>
17547void
17548print_h_submatrix_accessor(std::ostream &out,
17549 const std::string &name,
17551{
17552 out << name + std::string("([") << std::flush;
17553 print_vector_values(out, *(M.row_index_range), ",", false);
17554 out << "],[" << std::flush;
17555 print_vector_values(out, *(M.col_index_range), ",", false);
17556 out << "])";
17557}
17558
17559
17560template <int spacedim, typename Number = double>
17561void
17562print_h_h_submatrix_mmult_accessor(std::ostream &out,
17563 const std::string &name1,
17564 const HMatrix<spacedim, Number> &M1,
17565 const std::string &name2,
17566 const HMatrix<spacedim, Number> &M2)
17567{
17568 print_h_submatrix_accessor(out, name1, M1);
17569 out << " * ";
17570 print_h_submatrix_accessor(out, name2, M2);
17571}
17572
17573
17574template <int spacedim, typename Number>
17575void
17576hmatrix_solve_lu(const HMatrix<spacedim, Number> &L,
17578 Vector<Number> &x,
17579 const Vector<Number> &b)
17580{
17581 x = b;
17584}
17585
17586
17587template <int spacedim, typename Number>
17588void
17589hmatrix_solve_cholesky(const HMatrix<spacedim, Number> &L,
17590 Vector<Number> &x,
17591 const Vector<Number> &b)
17592{
17593 x = b;
17596}
17597
17598
17599template <int spacedim, typename Number>
17601 : type(UndefinedMatrixType)
17602 , state(HMatrixSupport::State::matrix)
17603 , property(HMatrixSupport::Property::general)
17604 , block_type(HMatrixSupport::BlockType::undefined_block)
17605 , dot_node_id(0)
17606 , submatrices(0)
17607 , parent(nullptr)
17608 , next_same_level_hmat_node(nullptr)
17609 , next_same_level_same_row_hmat_node(nullptr)
17610 , next_same_level_same_column_hmat_node(nullptr)
17611 , previous_same_level_same_row_hmat_node(nullptr)
17612 , previous_same_level_same_column_hmat_node(nullptr)
17613 , submatrix_index(submatrix_index_invalid)
17614 , leaf_set(0)
17615 , near_field_leaf_set(0)
17616 , far_field_leaf_set(0)
17617 , rkmatrix(nullptr)
17618 , fullmatrix(nullptr)
17619 , bc_node(nullptr)
17620 , row_index_range(nullptr)
17621 , col_index_range(nullptr)
17622 , m(0)
17623 , n(0)
17624 , Tind()
17625 , Sigma_P(0)
17626 , Sigma_R(0)
17627 , Sigma_F(0)
17628{}
17629
17630
17631template <int spacedim, typename Number>
17634 const unsigned int fixed_rank_k,
17635 const HMatrixSupport::Property property,
17636 const HMatrixSupport::BlockType block_type)
17637 : type(UndefinedMatrixType)
17638 , state(HMatrixSupport::State::matrix)
17639 , property(property)
17640 , block_type(block_type)
17641 , dot_node_id(0)
17642 , submatrices(0)
17643 , parent(nullptr)
17644 , next_same_level_hmat_node(nullptr)
17645 , next_same_level_same_row_hmat_node(nullptr)
17646 , next_same_level_same_column_hmat_node(nullptr)
17647 , previous_same_level_same_row_hmat_node(nullptr)
17648 , previous_same_level_same_column_hmat_node(nullptr)
17649 , submatrix_index(submatrix_index_invalid)
17650 , leaf_set(0)
17651 , near_field_leaf_set(0)
17652 , far_field_leaf_set(0)
17653 , rkmatrix(nullptr)
17654 , fullmatrix(nullptr)
17655 , bc_node(nullptr)
17656 , row_index_range(nullptr)
17657 , col_index_range(nullptr)
17658 , m(0)
17659 , n(0)
17660 , Tind()
17661 , Sigma_P(0)
17662 , Sigma_R(0)
17663 , Sigma_F(0)
17664{
17665 InitAndCreateHMatrixChildren(this, bct.get_root(), fixed_rank_k, property);
17669}
17670
17671
17672template <int spacedim, typename Number>
17675 bc_node,
17676 const unsigned int fixed_rank_k,
17677 const HMatrixSupport::Property property,
17678 const HMatrixSupport::BlockType block_type)
17679 : type(UndefinedMatrixType)
17680 , state(HMatrixSupport::State::matrix)
17681 , property(property)
17682 , block_type(block_type)
17683 , dot_node_id(0)
17684 , submatrices(0)
17685 , parent(nullptr)
17686 , next_same_level_hmat_node(nullptr)
17687 , next_same_level_same_row_hmat_node(nullptr)
17688 , next_same_level_same_column_hmat_node(nullptr)
17689 , previous_same_level_same_row_hmat_node(nullptr)
17690 , previous_same_level_same_column_hmat_node(nullptr)
17691 , submatrix_index(submatrix_index_invalid)
17692 , leaf_set(0)
17693 , near_field_leaf_set(0)
17694 , far_field_leaf_set(0)
17695 , rkmatrix(nullptr)
17696 , fullmatrix(nullptr)
17697 , bc_node(nullptr)
17698 , row_index_range(nullptr)
17699 , col_index_range(nullptr)
17700 , m(0)
17701 , n(0)
17702 , Tind()
17703 , Sigma_P(0)
17704 , Sigma_R(0)
17705 , Sigma_F(0)
17706{
17707 InitAndCreateHMatrixChildren(this, bc_node, fixed_rank_k, property);
17711}
17712
17713
17714template <int spacedim, typename Number>
17718 const unsigned int fixed_rank_k,
17719 const HMatrixSupport::BlockType block_type)
17720 : type(UndefinedMatrixType)
17721 , state(HMatrixSupport::State::matrix)
17722 , property(HMatrixSupport::Property::general)
17723 , block_type(block_type)
17724 , dot_node_id(0)
17725 , submatrices(0)
17726 , parent(nullptr)
17727 , next_same_level_hmat_node(nullptr)
17728 , next_same_level_same_row_hmat_node(nullptr)
17729 , next_same_level_same_column_hmat_node(nullptr)
17730 , previous_same_level_same_row_hmat_node(nullptr)
17731 , previous_same_level_same_column_hmat_node(nullptr)
17732 , submatrix_index(submatrix_index_invalid)
17733 , leaf_set(0)
17734 , near_field_leaf_set(0)
17735 , far_field_leaf_set(0)
17736 , rkmatrix(nullptr)
17737 , fullmatrix(nullptr)
17738 , bc_node(nullptr)
17739 , row_index_range(nullptr)
17740 , col_index_range(nullptr)
17741 , m(0)
17742 , n(0)
17743 , Tind()
17744 , Sigma_P(0)
17745 , Sigma_R(0)
17746 , Sigma_F(0)
17747{
17752
17753 InitAndCreateHMatrixChildren(this, bct.get_root(), fixed_rank_k, M, property);
17757}
17758
17759
17760template <int spacedim, typename Number>
17764 const HMatrixSupport::BlockType block_type)
17765 : type(UndefinedMatrixType)
17766 , state(HMatrixSupport::State::matrix)
17767 , property(HMatrixSupport::Property::general)
17768 , block_type(block_type)
17769 , dot_node_id(0)
17770 , submatrices(0)
17771 , parent(nullptr)
17772 , next_same_level_hmat_node(nullptr)
17773 , next_same_level_same_row_hmat_node(nullptr)
17774 , next_same_level_same_column_hmat_node(nullptr)
17775 , previous_same_level_same_row_hmat_node(nullptr)
17776 , previous_same_level_same_column_hmat_node(nullptr)
17777 , submatrix_index(submatrix_index_invalid)
17778 , leaf_set(0)
17779 , near_field_leaf_set(0)
17780 , far_field_leaf_set(0)
17781 , rkmatrix(nullptr)
17782 , fullmatrix(nullptr)
17783 , bc_node(nullptr)
17784 , row_index_range(nullptr)
17785 , col_index_range(nullptr)
17786 , m(0)
17787 , n(0)
17788 , Tind()
17789 , Sigma_P(0)
17790 , Sigma_R(0)
17791 , Sigma_F(0)
17792{
17797
17798 InitAndCreateHMatrixChildren(this, bct.get_root(), M, property);
17802}
17803
17804
17805template <int spacedim, typename Number>
17808 bc_node,
17810 const unsigned int fixed_rank_k,
17811 const HMatrixSupport::Property property,
17812 const HMatrixSupport::BlockType block_type)
17813 : type(UndefinedMatrixType)
17814 , state(HMatrixSupport::State::matrix)
17815 , property(property)
17816 , block_type(block_type)
17817 , dot_node_id(0)
17818 , submatrices(0)
17819 , parent(nullptr)
17820 , next_same_level_hmat_node(nullptr)
17821 , next_same_level_same_row_hmat_node(nullptr)
17822 , next_same_level_same_column_hmat_node(nullptr)
17823 , previous_same_level_same_row_hmat_node(nullptr)
17824 , previous_same_level_same_column_hmat_node(nullptr)
17825 , submatrix_index(submatrix_index_invalid)
17826 , leaf_set(0)
17827 , near_field_leaf_set(0)
17828 , far_field_leaf_set(0)
17829 , rkmatrix(nullptr)
17830 , fullmatrix(nullptr)
17831 , bc_node(nullptr)
17832 , row_index_range(nullptr)
17833 , col_index_range(nullptr)
17834 , m(0)
17835 , n(0)
17836 , Tind()
17837 , Sigma_P(0)
17838 , Sigma_R(0)
17839 , Sigma_F(0)
17840{
17841 InitAndCreateHMatrixChildren(this, bc_node, fixed_rank_k, M, property);
17845}
17846
17847
17848template <int spacedim, typename Number>
17851 bc_node,
17853 const HMatrixSupport::Property property,
17854 const HMatrixSupport::BlockType block_type)
17855 : type(UndefinedMatrixType)
17856 , state(HMatrixSupport::State::matrix)
17857 , property(property)
17858 , block_type(block_type)
17859 , dot_node_id(0)
17860 , submatrices(0)
17861 , parent(nullptr)
17862 , next_same_level_hmat_node(nullptr)
17863 , next_same_level_same_row_hmat_node(nullptr)
17864 , next_same_level_same_column_hmat_node(nullptr)
17865 , previous_same_level_same_row_hmat_node(nullptr)
17866 , previous_same_level_same_column_hmat_node(nullptr)
17867 , submatrix_index(submatrix_index_invalid)
17868 , leaf_set(0)
17869 , near_field_leaf_set(0)
17870 , far_field_leaf_set(0)
17871 , rkmatrix(nullptr)
17872 , fullmatrix(nullptr)
17873 , bc_node(nullptr)
17874 , row_index_range(nullptr)
17875 , col_index_range(nullptr)
17876 , m(0)
17877 , n(0)
17878 , Tind()
17879 , Sigma_P(0)
17880 , Sigma_R(0)
17881 , Sigma_F(0)
17882{
17883 InitAndCreateHMatrixChildren(this, bc_node, M, property);
17887}
17888
17889
17890template <int spacedim, typename Number>
17893 bc_node,
17895 const HMatrixSupport::Property property,
17896 const HMatrixSupport::BlockType block_type)
17897 : type(UndefinedMatrixType)
17898 , state(HMatrixSupport::State::matrix)
17899 , property(property)
17900 , block_type(block_type)
17901 , dot_node_id(0)
17902 , submatrices(0)
17903 , parent(nullptr)
17904 , next_same_level_hmat_node(nullptr)
17905 , next_same_level_same_row_hmat_node(nullptr)
17906 , next_same_level_same_column_hmat_node(nullptr)
17907 , previous_same_level_same_row_hmat_node(nullptr)
17908 , previous_same_level_same_column_hmat_node(nullptr)
17909 , submatrix_index(submatrix_index_invalid)
17910 , leaf_set(0)
17911 , near_field_leaf_set(0)
17912 , far_field_leaf_set(0)
17913 , rkmatrix(nullptr)
17914 , fullmatrix(nullptr)
17915 , bc_node(nullptr)
17916 , row_index_range(nullptr)
17917 , col_index_range(nullptr)
17918 , m(0)
17919 , n(0)
17920 , Tind(std::move(H.Tind))
17921 , Sigma_P(0)
17922 , Sigma_R(0)
17923 , Sigma_F(0)
17924{
17925 InitAndCreateHMatrixChildren(this, bc_node, std::move(H));
17929}
17930
17931
17932template <int spacedim, typename Number>
17936 const HMatrixSupport::Property property,
17937 const HMatrixSupport::BlockType block_type)
17938 : type(UndefinedMatrixType)
17939 , state(HMatrixSupport::State::matrix)
17940 , property(property)
17941 , block_type(block_type)
17942 , dot_node_id(0)
17943 , submatrices(0)
17944 , parent(nullptr)
17945 , next_same_level_hmat_node(nullptr)
17946 , next_same_level_same_row_hmat_node(nullptr)
17947 , next_same_level_same_column_hmat_node(nullptr)
17948 , previous_same_level_same_row_hmat_node(nullptr)
17949 , previous_same_level_same_column_hmat_node(nullptr)
17950 , submatrix_index(submatrix_index_invalid)
17951 , leaf_set(0)
17952 , near_field_leaf_set(0)
17953 , far_field_leaf_set(0)
17954 , rkmatrix(nullptr)
17955 , fullmatrix(nullptr)
17956 , bc_node(nullptr)
17957 , row_index_range(nullptr)
17958 , col_index_range(nullptr)
17959 , m(0)
17960 , n(0)
17961 , Tind(std::move(H.Tind))
17962 , Sigma_P(0)
17963 , Sigma_R(0)
17964 , Sigma_F(0)
17965{
17966 InitAndCreateHMatrixChildren(this, bct.get_root(), std::move(H));
17970}
17971
17972
17973template <int spacedim, typename Number>
17975 : type(UndefinedMatrixType)
17976 , state(HMatrixSupport::State::matrix)
17977 , property(HMatrixSupport::Property::general)
17978 , block_type(HMatrixSupport::BlockType::undefined_block)
17979 , dot_node_id(0)
17980 , submatrices(0)
17981 , parent(nullptr)
17982 , next_same_level_hmat_node(nullptr)
17983 , next_same_level_same_row_hmat_node(nullptr)
17984 , next_same_level_same_column_hmat_node(nullptr)
17985 , previous_same_level_same_row_hmat_node(nullptr)
17986 , previous_same_level_same_column_hmat_node(nullptr)
17987 , submatrix_index(submatrix_index_invalid)
17988 , leaf_set(0)
17989 , near_field_leaf_set(0)
17990 , far_field_leaf_set(0)
17991 , rkmatrix(nullptr)
17992 , fullmatrix(nullptr)
17993 , bc_node(nullptr)
17994 , row_index_range(nullptr)
17995 , col_index_range(nullptr)
17996 , m(0)
17997 , n(0)
17998 , Tind()
17999 , Sigma_P(0)
18000 , Sigma_R(0)
18001 , Sigma_F(0)
18002{
18003 copy_hmatrix(*this, H);
18007}
18008
18009
18010template <int spacedim, typename Number>
18012 : type(H.type)
18013 , state(H.state)
18014 , property(H.property)
18015 , block_type(H.block_type)
18016 , dot_node_id(H.dot_node_id)
18017 , submatrices(H.submatrices)
18018 , parent(H.parent)
18019 , next_same_level_hmat_node(H.next_same_level_hmat_node)
18020 , next_same_level_same_row_hmat_node(H.next_same_level_same_row_hmat_node)
18021 , next_same_level_same_column_hmat_node(
18022 H.next_same_level_same_column_hmat_node)
18023 , previous_same_level_same_row_hmat_node(
18024 H.previous_same_level_same_row_hmat_node)
18025 , previous_same_level_same_column_hmat_node(
18026 H.previous_same_level_same_column_hmat_node)
18027 , submatrix_index(H.submatrix_index)
18028 , leaf_set(H.leaf_set)
18029 , near_field_leaf_set(H.near_field_leaf_set)
18030 , far_field_leaf_set(H.far_field_leaf_set)
18031 , rkmatrix(H.rkmatrix)
18032 , fullmatrix(H.fullmatrix)
18033 , bc_node(H.bc_node)
18034 , row_index_range(H.row_index_range)
18035 , col_index_range(H.col_index_range)
18036 , m(H.m)
18037 , n(H.n)
18038 , Tind(std::move(H.Tind))
18039 , Sigma_P(H.Sigma_P)
18040 , Sigma_R(H.Sigma_R)
18041 , Sigma_F(H.Sigma_F)
18042{
18043 H.clear_hmat_node();
18044}
18045
18046
18047template <int spacedim, typename Number>
18048void
18050 const BlockClusterTree<spacedim,
18051 typename numbers::NumberTraits<Number>::real_type>
18052 &bct,
18053 const unsigned int fixed_rank_k,
18054 const HMatrixSupport::Property property,
18055 const HMatrixSupport::BlockType block_type)
18056{
18057 release();
18058
18059 this->property = property;
18060 this->block_type = block_type;
18061
18063 bct.get_root(),
18064 fixed_rank_k,
18065 this->property);
18066 build_leaf_set();
18067 link_hmat_nodes_on_same_levels();
18068 set_default_vmult_strategy();
18069}
18070
18071
18072template <int spacedim, typename Number>
18073void
18076 bc_node,
18077 const unsigned int fixed_rank_k,
18078 const HMatrixSupport::Property property,
18079 const HMatrixSupport::BlockType block_type)
18080{
18081 release();
18082
18083 this->property = property;
18084 this->block_type = block_type;
18085
18086 InitAndCreateHMatrixChildren(this, bc_node, fixed_rank_k, this->property);
18087 build_leaf_set();
18088 link_hmat_nodes_on_same_levels();
18089 set_default_vmult_strategy();
18090}
18091
18092
18093template <int spacedim, typename Number>
18096{
18100 if (this != &H)
18101 {
18102 release();
18103 copy_hmatrix_node((*this), std::move(H));
18104 H.clear_hmat_node();
18105
18118 if (bc_node->is_root() && submatrices.size() == 0)
18119 {
18120 // When there is only one root node in the \hmat hierarchy, the
18121 // \hmat type can only be @p FullMatrixType.
18122 Assert(type == HMatrixType::FullMatrixType,
18123 ExcInvalidHMatrixType(type));
18124 build_leaf_set();
18129 }
18130
18131 set_default_vmult_strategy();
18132 }
18133
18134 return (*this);
18135}
18136
18137
18138template <int spacedim, typename Number>
18141{
18142 release();
18143 copy_hmatrix(*this, H);
18144 build_leaf_set();
18145 link_hmat_nodes_on_same_levels();
18146 set_default_vmult_strategy();
18147
18148 return (*this);
18149}
18150
18151
18152template <int spacedim, typename Number>
18153template <typename MatrixType>
18154void
18156{
18157 M.reinit(m, n);
18158 _convertToFullMatrix(M, property);
18159
18163 set_property_for_converted_fullmatrix(M);
18164}
18165
18166
18167template <int spacedim, typename Number>
18168template <typename MatrixType>
18169void
18171 MatrixType &M,
18172 const HMatrixSupport::Property top_hmat_property) const
18173{
18174 LAPACKFullMatrixExt<Number> matrix_block;
18175
18176 switch (type)
18177 {
18178 case FullMatrixType:
18179 Assert(fullmatrix, ExcInternalError());
18180
18181 switch (top_hmat_property)
18182 {
18183 case HMatrixSupport::Property::general: {
18184 for (size_type i = 0; i < m; i++)
18185 {
18186 for (size_type j = 0; j < n; j++)
18187 {
18188 M((*row_index_range)[0] + i,
18189 (*col_index_range)[0] + j) = (*fullmatrix)(i, j);
18190 }
18191 }
18192
18193 break;
18194 }
18195 case HMatrixSupport::Property::symmetric:
18196 case HMatrixSupport::Property::hermite_symmetric:
18197 case HMatrixSupport::Property::lower_triangular: {
18206 if (this->block_type ==
18207 HMatrixSupport::BlockType::diagonal_block)
18208 {
18209 for (size_type i = 0; i < m; i++)
18210 {
18211 for (size_type j = 0; j <= i; j++)
18212 {
18213 M((*row_index_range)[0] + i,
18214 (*col_index_range)[0] + j) = (*fullmatrix)(i, j);
18215 }
18216 }
18217 }
18218 else if (this->block_type ==
18219 HMatrixSupport::BlockType::lower_triangular_block)
18220 {
18221 for (size_type i = 0; i < m; i++)
18222 {
18223 for (size_type j = 0; j < n; j++)
18224 {
18225 M((*row_index_range)[0] + i,
18226 (*col_index_range)[0] + j) = (*fullmatrix)(i, j);
18227 }
18228 }
18229 }
18230
18231 break;
18232 }
18233 case HMatrixSupport::Property::upper_triangular: {
18242 if (this->block_type ==
18243 HMatrixSupport::BlockType::diagonal_block)
18244 {
18245 for (size_type i = 0; i < m; i++)
18246 {
18247 for (size_type j = i; j < n; j++)
18248 {
18249 M((*row_index_range)[0] + i,
18250 (*col_index_range)[0] + j) = (*fullmatrix)(i, j);
18251 }
18252 }
18253 }
18254 else if (this->block_type ==
18255 HMatrixSupport::BlockType::upper_triangular_block)
18256 {
18257 for (size_type i = 0; i < m; i++)
18258 {
18259 for (size_type j = 0; j < n; j++)
18260 {
18261 M((*row_index_range)[0] + i,
18262 (*col_index_range)[0] + j) = (*fullmatrix)(i, j);
18263 }
18264 }
18265 }
18266
18267 break;
18268 }
18269 default: {
18270 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
18271
18272 break;
18273 }
18274 }
18275
18276 break;
18277 case RkMatrixType:
18278 Assert(rkmatrix, ExcInternalError());
18279
18280 switch (top_hmat_property)
18281 {
18282 case HMatrixSupport::Property::general: {
18283 if (rkmatrix->convertToFullMatrix(matrix_block))
18284 {
18289 for (size_type i = 0; i < m; i++)
18290 {
18291 for (size_type j = 0; j < n; j++)
18292 {
18293 M((*row_index_range)[0] + i,
18294 (*col_index_range)[0] + j) = matrix_block(i, j);
18295 }
18296 }
18297 }
18298
18299 break;
18300 }
18301 case HMatrixSupport::Property::symmetric:
18302 case HMatrixSupport::Property::hermite_symmetric:
18303 case HMatrixSupport::Property::lower_triangular: {
18312 if (this->block_type ==
18313 HMatrixSupport::BlockType::diagonal_block)
18314 {
18315 Assert(
18316 false,
18317 ExcMessage(
18318 "Rank-k matrix cannot belong to the diagonal part!"));
18319 }
18320 else if (this->block_type ==
18321 HMatrixSupport::BlockType::lower_triangular_block)
18322 {
18323 if (rkmatrix->convertToFullMatrix(matrix_block))
18324 {
18330 for (size_type i = 0; i < m; i++)
18331 {
18332 for (size_type j = 0; j < n; j++)
18333 {
18334 M((*row_index_range)[0] + i,
18335 (*col_index_range)[0] + j) =
18336 matrix_block(i, j);
18337 }
18338 }
18339 }
18340 }
18341
18342 break;
18343 }
18344 case HMatrixSupport::Property::upper_triangular: {
18353 if (this->block_type ==
18354 HMatrixSupport::BlockType::diagonal_block)
18355 {
18356 Assert(
18357 false,
18358 ExcMessage(
18359 "Rank-k matrix cannot belong to the diagonal part!"));
18360 }
18361 else if (this->block_type ==
18362 HMatrixSupport::BlockType::upper_triangular_block)
18363 {
18364 if (rkmatrix->convertToFullMatrix(matrix_block))
18365 {
18371 for (size_type i = 0; i < m; i++)
18372 {
18373 for (size_type j = 0; j < n; j++)
18374 {
18375 M((*row_index_range)[0] + i,
18376 (*col_index_range)[0] + j) =
18377 matrix_block(i, j);
18378 }
18379 }
18380 }
18381 }
18382
18383 break;
18384 }
18385 default: {
18386 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
18387
18388 break;
18389 }
18390 }
18391
18392 break;
18394 for (HMatrix *submatrix : submatrices)
18395 {
18396 submatrix->_convertToFullMatrix(M, top_hmat_property);
18397 }
18398
18399 break;
18400 default:
18401 Assert(false, ExcInvalidHMatrixType(type));
18402 break;
18403 }
18404}
18405
18406
18407template <int spacedim, typename Number>
18408bool
18410 const HMatrixSupport::Property top_hmat_property) const
18411{
18412 switch (top_hmat_property)
18413 {
18414 case HMatrixSupport::Property::general:
18415 return true;
18416
18417 case HMatrixSupport::Property::symmetric:
18418 if (block_type == HMatrixSupport::BlockType::diagonal_block ||
18419 block_type == HMatrixSupport::BlockType::lower_triangular_block)
18420 {
18421 return true;
18422 }
18423 else
18424 {
18425 return false;
18426 }
18427
18428 case HMatrixSupport::Property::hermite_symmetric:
18429 if (block_type == HMatrixSupport::BlockType::diagonal_block ||
18430 block_type == HMatrixSupport::BlockType::lower_triangular_block)
18431 {
18432 return true;
18433 }
18434 else
18435 {
18436 return false;
18437 }
18438
18439 case HMatrixSupport::Property::upper_triangular:
18440 if (block_type == HMatrixSupport::BlockType::diagonal_block ||
18441 block_type == HMatrixSupport::BlockType::upper_triangular_block)
18442 {
18443 return true;
18444 }
18445 else
18446 {
18447 return false;
18448 }
18449
18450 case HMatrixSupport::Property::lower_triangular:
18451 if (block_type == HMatrixSupport::BlockType::diagonal_block ||
18452 block_type == HMatrixSupport::BlockType::lower_triangular_block)
18453 {
18454 return true;
18455 }
18456 else
18457 {
18458 return false;
18459 }
18460
18461 default:
18462 return false;
18463 }
18464}
18465
18466
18467template <int spacedim, typename Number>
18468void
18470 std::vector<HMatrix *> &total_leaf_set,
18471 std::vector<HMatrix *> &total_near_field_leaf_set,
18472 std::vector<HMatrix *> &total_far_field_leaf_set,
18473 const HMatrixSupport::Property top_hmat_property) const
18474{
18475 if (is_current_hmat_node_nonemtpy(top_hmat_property))
18476 {
18477 switch (type)
18478 {
18479 case FullMatrixType: {
18480 total_leaf_set.push_back(const_cast<HMatrix *>(this));
18481 total_near_field_leaf_set.push_back(const_cast<HMatrix *>(this));
18482
18483 break;
18484 }
18485 case RkMatrixType: {
18486 total_leaf_set.push_back(const_cast<HMatrix *>(this));
18487 total_far_field_leaf_set.push_back(const_cast<HMatrix *>(this));
18488
18489 break;
18490 }
18492 for (HMatrix *submatrix : submatrices)
18493 {
18494 submatrix->_build_leaf_set_z_traversal(
18495 total_leaf_set,
18496 total_near_field_leaf_set,
18497 total_far_field_leaf_set,
18498 top_hmat_property);
18499 }
18500
18501 break;
18502 }
18503 default: {
18504 Assert(false, ExcInvalidHMatrixType(type));
18505
18506 break;
18507 }
18508 }
18509 }
18510}
18511
18512
18513template <int spacedim, typename Number>
18514void
18516 std::vector<HMatrix *> &total_leaf_set,
18517 std::vector<HMatrix *> &total_near_field_leaf_set,
18518 std::vector<HMatrix *> &total_far_field_leaf_set,
18519 HilbertBlockType current_hilbert_block_type,
18520 const HMatrixSupport::Property top_hmat_property) const
18521{
18522 if (is_current_hmat_node_nonemtpy(top_hmat_property))
18523 {
18524 switch (type)
18525 {
18526 case FullMatrixType: {
18527 total_leaf_set.push_back(const_cast<HMatrix *>(this));
18528 total_near_field_leaf_set.push_back(const_cast<HMatrix *>(this));
18529
18530 break;
18531 }
18532 case RkMatrixType: {
18533 total_leaf_set.push_back(const_cast<HMatrix *>(this));
18534 total_far_field_leaf_set.push_back(const_cast<HMatrix *>(this));
18535
18536 break;
18537 }
18542 AssertDimension(submatrices.size(), 4);
18543
18544 switch (current_hilbert_block_type)
18545 {
18546 case HilbertBlockType::A: {
18547 submatrices[2]->_build_leaf_set_hilbert_traversal(
18548 total_leaf_set,
18549 total_near_field_leaf_set,
18550 total_far_field_leaf_set,
18551 HilbertBlockType::B,
18552 top_hmat_property);
18553
18554 submatrices[0]->_build_leaf_set_hilbert_traversal(
18555 total_leaf_set,
18556 total_near_field_leaf_set,
18557 total_far_field_leaf_set,
18558 HilbertBlockType::A,
18559 top_hmat_property);
18560
18561 submatrices[1]->_build_leaf_set_hilbert_traversal(
18562 total_leaf_set,
18563 total_near_field_leaf_set,
18564 total_far_field_leaf_set,
18565 HilbertBlockType::A,
18566 top_hmat_property);
18567
18568 submatrices[3]->_build_leaf_set_hilbert_traversal(
18569 total_leaf_set,
18570 total_near_field_leaf_set,
18571 total_far_field_leaf_set,
18572 HilbertBlockType::C,
18573 top_hmat_property);
18574
18575 break;
18576 }
18577 case HilbertBlockType::B: {
18578 submatrices[2]->_build_leaf_set_hilbert_traversal(
18579 total_leaf_set,
18580 total_near_field_leaf_set,
18581 total_far_field_leaf_set,
18582 HilbertBlockType::A,
18583 top_hmat_property);
18584
18585 submatrices[3]->_build_leaf_set_hilbert_traversal(
18586 total_leaf_set,
18587 total_near_field_leaf_set,
18588 total_far_field_leaf_set,
18589 HilbertBlockType::B,
18590 top_hmat_property);
18591
18592 submatrices[1]->_build_leaf_set_hilbert_traversal(
18593 total_leaf_set,
18594 total_near_field_leaf_set,
18595 total_far_field_leaf_set,
18596 HilbertBlockType::B,
18597 top_hmat_property);
18598
18599 submatrices[0]->_build_leaf_set_hilbert_traversal(
18600 total_leaf_set,
18601 total_near_field_leaf_set,
18602 total_far_field_leaf_set,
18603 HilbertBlockType::D,
18604 top_hmat_property);
18605
18606 break;
18607 }
18608 case HilbertBlockType::C: {
18609 submatrices[1]->_build_leaf_set_hilbert_traversal(
18610 total_leaf_set,
18611 total_near_field_leaf_set,
18612 total_far_field_leaf_set,
18613 HilbertBlockType::D,
18614 top_hmat_property);
18615
18616 submatrices[0]->_build_leaf_set_hilbert_traversal(
18617 total_leaf_set,
18618 total_near_field_leaf_set,
18619 total_far_field_leaf_set,
18620 HilbertBlockType::C,
18621 top_hmat_property);
18622
18623 submatrices[2]->_build_leaf_set_hilbert_traversal(
18624 total_leaf_set,
18625 total_near_field_leaf_set,
18626 total_far_field_leaf_set,
18627 HilbertBlockType::C,
18628 top_hmat_property);
18629
18630 submatrices[3]->_build_leaf_set_hilbert_traversal(
18631 total_leaf_set,
18632 total_near_field_leaf_set,
18633 total_far_field_leaf_set,
18634 HilbertBlockType::A,
18635 top_hmat_property);
18636
18637 break;
18638 }
18639 case HilbertBlockType::D: {
18640 submatrices[1]->_build_leaf_set_hilbert_traversal(
18641 total_leaf_set,
18642 total_near_field_leaf_set,
18643 total_far_field_leaf_set,
18644 HilbertBlockType::C,
18645 top_hmat_property);
18646
18647 submatrices[3]->_build_leaf_set_hilbert_traversal(
18648 total_leaf_set,
18649 total_near_field_leaf_set,
18650 total_far_field_leaf_set,
18651 HilbertBlockType::D,
18652 top_hmat_property);
18653
18654 submatrices[2]->_build_leaf_set_hilbert_traversal(
18655 total_leaf_set,
18656 total_near_field_leaf_set,
18657 total_far_field_leaf_set,
18658 HilbertBlockType::D,
18659 top_hmat_property);
18660
18661 submatrices[0]->_build_leaf_set_hilbert_traversal(
18662 total_leaf_set,
18663 total_near_field_leaf_set,
18664 total_far_field_leaf_set,
18665 HilbertBlockType::B,
18666 top_hmat_property);
18667
18668 break;
18669 }
18670 }
18671
18672 break;
18673 }
18674 default: {
18675 Assert(false, ExcInvalidHMatrixType(type));
18676
18677 break;
18678 }
18679 }
18680 }
18681}
18682
18683
18684template <int spacedim, typename Number>
18685void
18688 const unsigned int fixed_rank)
18689{
18693 if (submatrices.size() > 0)
18694 {
18699 Assert(type == HierarchicalMatrixType, ExcInvalidHMatrixType(type));
18700
18706 distribute_sigma_r_and_f_to_leaves(fixed_rank);
18707
18713 for (HMatrix<spacedim, Number> *submatrix : submatrices)
18714 {
18715 Assert(submatrix, ExcInternalError());
18716
18717 submatrix->distribute_all_non_leaf_nodes_sigma_r_and_f_to_leaves(
18718 fixed_rank);
18719 }
18720 }
18721}
18722
18723
18724template <int spacedim, typename Number>
18725void
18727 const unsigned int fixed_rank)
18728{
18729 if (Sigma_R.size() > 0 || Sigma_F.size() > 0)
18730 {
18731 _distribute_sigma_r_and_f_to_leaves(*this, fixed_rank);
18732
18733 for (auto &rkmatrix_in_starting_hmat : Sigma_R)
18734 {
18735 if (rkmatrix_in_starting_hmat != nullptr)
18736 {
18737 delete rkmatrix_in_starting_hmat;
18738 rkmatrix_in_starting_hmat = nullptr;
18739 }
18740 }
18741
18742 Sigma_R.clear();
18743
18744 for (auto &fullmatrix_in_starting_hmat : Sigma_F)
18745 {
18746 if (fullmatrix_in_starting_hmat != nullptr)
18747 {
18748 delete fullmatrix_in_starting_hmat;
18749 fullmatrix_in_starting_hmat = nullptr;
18750 }
18751 }
18752
18753 Sigma_F.clear();
18754 }
18755}
18756
18757
18758template <int spacedim, typename Number>
18759void
18761 HMatrix<spacedim, Number> &starting_hmat,
18762 const unsigned int fixed_rank)
18763{
18764 if (submatrices.size() > 0)
18765 {
18766 for (HMatrix<spacedim, Number> *submatrix : submatrices)
18767 {
18768 submatrix->_distribute_sigma_r_and_f_to_leaves(starting_hmat,
18769 fixed_rank);
18770 }
18771 }
18772 else
18773 {
18774 switch (type)
18775 {
18776 case FullMatrixType: {
18781 for (RkMatrix<Number> *rkmatrix_in_starting_hmat :
18782 starting_hmat.Sigma_R)
18783 {
18784 Assert(rkmatrix_in_starting_hmat, ExcInternalError());
18785
18786 LAPACKFullMatrixExt<Number> fullmatrix_restricted;
18787
18788 rkmatrix_in_starting_hmat->restrictToFullMatrix(
18789 *starting_hmat.row_index_range,
18790 *starting_hmat.col_index_range,
18791 fullmatrix_restricted,
18792 *row_index_range,
18793 *col_index_range);
18794
18795 fullmatrix->add(fullmatrix_restricted);
18796 }
18797
18802 for (LAPACKFullMatrixExt<Number> *fullmatrix_in_starting_hmat :
18803 starting_hmat.Sigma_F)
18804 {
18805 Assert(fullmatrix_in_starting_hmat, ExcInternalError());
18806
18807 LAPACKFullMatrixExt<Number> fullmatrix_restricted(
18808 *row_index_range,
18809 *col_index_range,
18810 *fullmatrix_in_starting_hmat,
18811 *starting_hmat.row_index_range,
18812 *starting_hmat.col_index_range);
18813
18814 fullmatrix->add(fullmatrix_restricted);
18815 }
18816
18817 break;
18818 }
18819 case RkMatrixType: {
18824 for (RkMatrix<Number> *rkmatrix_in_starting_hmat :
18825 starting_hmat.Sigma_R)
18826 {
18827 Assert(rkmatrix_in_starting_hmat, ExcInternalError());
18828
18829 RkMatrix<Number> rkmatrix_restricted(
18830 *row_index_range,
18831 *col_index_range,
18832 *rkmatrix_in_starting_hmat,
18833 *starting_hmat.row_index_range,
18834 *starting_hmat.col_index_range);
18835
18836 if (fixed_rank == 0)
18837 {
18838 rkmatrix->add(rkmatrix_restricted);
18839 }
18840 else
18841 {
18842 rkmatrix->add(rkmatrix_restricted, fixed_rank);
18843 }
18844 }
18845
18850 for (LAPACKFullMatrixExt<Number> *fullmatrix_in_starting_hmat :
18851 starting_hmat.Sigma_F)
18852 {
18853 Assert(fullmatrix_in_starting_hmat, ExcInternalError());
18854
18855 RkMatrix<Number> rkmatrix_restricted(
18856 *row_index_range,
18857 *col_index_range,
18858 *fullmatrix_in_starting_hmat,
18859 *starting_hmat.row_index_range,
18860 *starting_hmat.col_index_range);
18861
18862 if (fixed_rank == 0)
18863 {
18864 rkmatrix->add(rkmatrix_restricted);
18865 }
18866 else
18867 {
18868 rkmatrix->add(rkmatrix_restricted, fixed_rank);
18869 }
18870 }
18871
18872 break;
18873 }
18874 default: {
18875 Assert(false, ExcInvalidHMatrixType(type));
18876 break;
18877 }
18878 }
18879 }
18880}
18881
18882
18883template <int spacedim, typename Number>
18884void
18886{
18887 if (rkmatrix != nullptr)
18888 {
18889 delete rkmatrix;
18890 rkmatrix = nullptr;
18891 }
18892
18893 if (fullmatrix != nullptr)
18894 {
18895 delete fullmatrix;
18896 fullmatrix = nullptr;
18897 }
18898
18899 for (auto submatrix : submatrices)
18900 {
18907 if (submatrix != nullptr)
18908 {
18909 delete submatrix;
18910 }
18911 }
18912
18913 submatrices.clear();
18914 leaf_set.clear();
18915 near_field_leaf_set.clear();
18916 far_field_leaf_set.clear();
18917
18918 type = UndefinedMatrixType;
18919 state = HMatrixSupport::State::matrix;
18920 property = HMatrixSupport::Property::general,
18921 block_type = HMatrixSupport::BlockType::undefined_block;
18922 dot_node_id = 0;
18923 bc_node = nullptr;
18924 parent = nullptr;
18925 next_same_level_hmat_node = nullptr;
18926 next_same_level_same_row_hmat_node = nullptr;
18927 next_same_level_same_column_hmat_node = nullptr;
18928 previous_same_level_same_row_hmat_node = nullptr;
18929 previous_same_level_same_column_hmat_node = nullptr;
18930 submatrix_index = submatrix_index_invalid;
18931 row_index_range = nullptr;
18932 col_index_range = nullptr;
18933 m = 0;
18934 n = 0;
18935
18936 Sigma_P.clear();
18937
18938 for (auto &r : Sigma_R)
18939 {
18940 if (r != nullptr)
18941 {
18942 delete r;
18943 r = nullptr;
18944 }
18945 }
18946 Sigma_R.clear();
18947
18948 for (auto &f : Sigma_F)
18949 {
18950 if (f != nullptr)
18951 {
18952 delete f;
18953 f = nullptr;
18954 }
18955 }
18956 Sigma_F.clear();
18957
18958 Tind.release();
18959}
18960
18961
18962template <int spacedim, typename Number>
18963void
18965{
18969 if (submatrices.size() > 0)
18970 {
18971 Assert(type == HierarchicalMatrixType, ExcInvalidHMatrixType(type));
18972
18973 for (HMatrix *submatrix : submatrices)
18974 {
18975 submatrix->clear();
18976 }
18977 }
18978
18982 clear_hmat_node();
18983}
18984
18985
18986template <int spacedim, typename Number>
18987void
18989{
18990 type = UndefinedMatrixType;
18991 state = HMatrixSupport::State::matrix;
18992 property = HMatrixSupport::Property::general;
18993 block_type = HMatrixSupport::BlockType::undefined_block;
18994 dot_node_id = 0;
18995 submatrices.clear();
18996 parent = nullptr;
18997 next_same_level_hmat_node = nullptr;
18998 next_same_level_same_row_hmat_node = nullptr;
18999 next_same_level_same_column_hmat_node = nullptr;
19000 previous_same_level_same_row_hmat_node = nullptr;
19001 previous_same_level_same_column_hmat_node = nullptr;
19002 submatrix_index = submatrix_index_invalid;
19003 leaf_set.clear();
19004 near_field_leaf_set.clear();
19005 far_field_leaf_set.clear();
19006 rkmatrix = nullptr;
19007 fullmatrix = nullptr;
19008 bc_node = nullptr;
19009 row_index_range = nullptr;
19010 col_index_range = nullptr;
19011 m = 0;
19012 n = 0;
19013 Sigma_P.clear();
19014 Sigma_R.clear();
19015 Sigma_F.clear();
19016 Tind.clear();
19017}
19018
19019
19020template <int spacedim, typename Number>
19021void
19023{
19024 for (auto submatrix : submatrices)
19025 {
19026 submatrix->clear_lu_or_cholesky_task_nodes();
19027 }
19028
19029 clear_lu_or_cholesky_task_nodes_in_hmat();
19030}
19031
19032
19033template <int spacedim, typename Number>
19034void
19036{
19037 factorize_lu_or_cholesky_graph_node.reset();
19038 update_lu_or_cholesky_graph_nodes.clear();
19039 solve_upper_or_lower_lu_or_cholesky_graph_node.reset();
19040}
19041
19042
19043template <int spacedim, typename Number>
19045{
19046 release();
19047}
19048
19049
19050template <int spacedim, typename Number>
19051inline HMatrixType
19053{
19054 return type;
19055}
19056
19057
19058template <int spacedim, typename Number>
19059inline bool
19061{
19062 return bc_node->is_root();
19063}
19064
19065
19066template <int spacedim, typename Number>
19067inline bool
19069{
19070 return (type == HMatrixType::FullMatrixType);
19071}
19072
19073
19074template <int spacedim, typename Number>
19075inline bool
19077{
19078 return (type == HMatrixType::RkMatrixType);
19079}
19080
19081
19082template <int spacedim, typename Number>
19083inline bool
19085{
19086 return (type == HMatrixType::FullMatrixType ||
19088}
19089
19090
19091template <int spacedim, typename Number>
19094{
19095 return m;
19096}
19097
19098
19099template <int spacedim, typename Number>
19100inline unsigned int
19102{
19104 bc_node->get_data_reference().get_tau_node()->get_child_num() :
19105 0;
19106}
19107
19108
19109template <int spacedim, typename Number>
19110inline unsigned int
19112{
19114 bc_node->get_data_reference().get_sigma_node()->get_child_num() :
19115 0;
19116}
19117
19118
19119template <int spacedim, typename Number>
19122{
19123 return property;
19124}
19125
19126
19127template <int spacedim, typename Number>
19128inline void
19130 const HMatrixSupport::Property property)
19131{
19132 this->property = property;
19133}
19134
19135
19136template <int spacedim, typename Number>
19137void
19140{
19141 switch (M.get_property())
19142 {
19143 case LAPACKSupport::Property::general: {
19144 property = HMatrixSupport::Property::general;
19145
19146 break;
19147 }
19148 case LAPACKSupport::Property::symmetric: {
19149 property = HMatrixSupport::Property::symmetric;
19150
19151 break;
19152 }
19153 case LAPACKSupport::Property::hermite_symmetric: {
19154 property = HMatrixSupport::Property::hermite_symmetric;
19155
19156 break;
19157 }
19158 case LAPACKSupport::Property::upper_triangular: {
19159 property = HMatrixSupport::Property::upper_triangular;
19160
19161 break;
19162 }
19163 case LAPACKSupport::Property::lower_triangular: {
19164 property = HMatrixSupport::Property::lower_triangular;
19165
19166 break;
19167 }
19168 default: {
19169 Assert(false, ExcNotImplemented());
19170 break;
19171 }
19172 }
19173}
19174
19175
19176template <int spacedim, typename Number>
19177void
19179{
19180 switch (property)
19181 {
19182 case HMatrixSupport::Property::general: {
19191 this->set_current_matrix_property(property);
19192
19196 for (HMatrix<spacedim, Number> *hmat : submatrices)
19197 {
19198 hmat->set_property(property);
19199 }
19200
19201 break;
19202 }
19203 case HMatrixSupport::Property::symmetric: {
19208 Assert(
19209 block_type == HMatrixSupport::BlockType::diagonal_block,
19210 ExcMessage(
19211 "A symmetric H-matrix node should belong to the diagonal part!"));
19212
19213 this->set_current_matrix_property(property);
19214
19215 if (submatrices.size() > 0)
19216 {
19226 Assert(submatrices.size() ==
19228 ExcDimensionMismatch(
19229 submatrices.size(),
19231
19247 Assert(
19248 submatrices[0]->block_type ==
19249 HMatrixSupport::BlockType::diagonal_block,
19250 ExcMessage(
19251 "The first child matrix should belong to the diagonal part!"));
19252 Assert(
19253 submatrices[1]->block_type ==
19254 HMatrixSupport::BlockType::upper_triangular_block,
19255 ExcMessage(
19256 "The second child matrix should belong to the upper triangular part!"));
19257 Assert(
19258 submatrices[2]->block_type ==
19259 HMatrixSupport::BlockType::lower_triangular_block,
19260 ExcMessage(
19261 "The third child matrix should belong to the lower triangular part!"));
19262 Assert(
19263 submatrices[3]->block_type ==
19264 HMatrixSupport::BlockType::diagonal_block,
19265 ExcMessage(
19266 "The fourth child matrix should belong to the diagonal part!"));
19267
19272 submatrices[0]->set_property(this->property);
19273 submatrices[1]->set_property(HMatrixSupport::Property::general);
19274 submatrices[2]->set_property(HMatrixSupport::Property::general);
19275 submatrices[3]->set_property(this->property);
19276 }
19277 else
19278 {
19283 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
19284
19285 this->fullmatrix->set_property(
19286 LAPACKSupport::Property::symmetric);
19287 }
19288
19289 break;
19290 }
19291 case HMatrixSupport::Property::hermite_symmetric: {
19296 Assert(
19297 block_type == HMatrixSupport::BlockType::diagonal_block,
19298 ExcMessage(
19299 "An Hermite symmetric H-matrix node should belong to the diagonal part!"));
19300
19301 this->set_current_matrix_property(property);
19302
19303 if (submatrices.size() > 0)
19304 {
19314 Assert(submatrices.size() ==
19316 ExcDimensionMismatch(
19317 submatrices.size(),
19319
19335 Assert(
19336 submatrices[0]->block_type ==
19337 HMatrixSupport::BlockType::diagonal_block,
19338 ExcMessage(
19339 "The first child matrix should belong to the diagonal part!"));
19340 Assert(
19341 submatrices[1]->block_type ==
19342 HMatrixSupport::BlockType::upper_triangular_block,
19343 ExcMessage(
19344 "The second child matrix should belong to the upper triangular part!"));
19345 Assert(
19346 submatrices[2]->block_type ==
19347 HMatrixSupport::BlockType::lower_triangular_block,
19348 ExcMessage(
19349 "The third child matrix should belong to the lower triangular part!"));
19350 Assert(
19351 submatrices[3]->block_type ==
19352 HMatrixSupport::BlockType::diagonal_block,
19353 ExcMessage(
19354 "The fourth child matrix should belong to the diagonal part!"));
19355
19360 submatrices[0]->set_property(this->property);
19361 submatrices[1]->set_property(HMatrixSupport::Property::general);
19362 submatrices[2]->set_property(HMatrixSupport::Property::general);
19363 submatrices[3]->set_property(this->property);
19364 }
19365 else
19366 {
19371 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
19372
19373 this->fullmatrix->set_property(
19374 LAPACKSupport::Property::hermite_symmetric);
19375 }
19376
19377 break;
19378 }
19379 case HMatrixSupport::Property::upper_triangular: {
19384 Assert(
19385 block_type == HMatrixSupport::BlockType::diagonal_block,
19386 ExcMessage(
19387 "An upper triangular H-matrix node should belong to the diagonal part!"));
19388
19389 this->set_current_matrix_property(property);
19390
19391 if (submatrices.size() > 0)
19392 {
19402 Assert(submatrices.size() ==
19404 ExcDimensionMismatch(
19405 submatrices.size(),
19407
19415 Assert(
19416 submatrices[0]->block_type ==
19417 HMatrixSupport::BlockType::diagonal_block,
19418 ExcMessage(
19419 "The first child matrix should belong to the diagonal part!"));
19420 Assert(
19421 submatrices[1]->block_type ==
19422 HMatrixSupport::BlockType::upper_triangular_block,
19423 ExcMessage(
19424 "The second child matrix should belong to the upper triangular part!"));
19425 Assert(
19426 submatrices[2]->block_type ==
19427 HMatrixSupport::BlockType::lower_triangular_block,
19428 ExcMessage(
19429 "The third child matrix should belong to the lower triangular part!"));
19430 Assert(
19431 submatrices[3]->block_type ==
19432 HMatrixSupport::BlockType::diagonal_block,
19433 ExcMessage(
19434 "The fourth child matrix should belong to the diagonal part!"));
19435
19440 submatrices[0]->set_property(this->property);
19441 submatrices[1]->set_property(HMatrixSupport::Property::general);
19442 submatrices[2]->set_property(HMatrixSupport::Property::general);
19443 submatrices[3]->set_property(this->property);
19444 }
19445 else
19446 {
19451 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
19452
19453 this->fullmatrix->set_property(
19454 LAPACKSupport::Property::upper_triangular);
19455 }
19456
19457 break;
19458 }
19459 case HMatrixSupport::Property::lower_triangular: {
19464 Assert(
19465 block_type == HMatrixSupport::BlockType::diagonal_block,
19466 ExcMessage(
19467 "A lower triangular H-matrix node should belong to the diagonal part!"));
19468
19469 this->set_current_matrix_property(property);
19470
19471 if (submatrices.size() > 0)
19472 {
19482 Assert(submatrices.size() ==
19484 ExcDimensionMismatch(
19485 submatrices.size(),
19487
19495 Assert(
19496 submatrices[0]->block_type ==
19497 HMatrixSupport::BlockType::diagonal_block,
19498 ExcMessage(
19499 "The first child matrix should belong to the diagonal part!"));
19500 Assert(
19501 submatrices[1]->block_type ==
19502 HMatrixSupport::BlockType::upper_triangular_block,
19503 ExcMessage(
19504 "The second child matrix should belong to the upper triangular part!"));
19505 Assert(
19506 submatrices[2]->block_type ==
19507 HMatrixSupport::BlockType::lower_triangular_block,
19508 ExcMessage(
19509 "The third child matrix should belong to the lower triangular part!"));
19510 Assert(
19511 submatrices[3]->block_type ==
19512 HMatrixSupport::BlockType::diagonal_block,
19513 ExcMessage(
19514 "The fourth child matrix should belong to the diagonal part!"));
19515
19520 submatrices[0]->set_property(this->property);
19521 submatrices[1]->set_property(HMatrixSupport::Property::general);
19522 submatrices[2]->set_property(HMatrixSupport::Property::general);
19523 submatrices[3]->set_property(this->property);
19524 }
19525 else
19526 {
19531 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
19532
19533 this->fullmatrix->set_property(
19534 LAPACKSupport::Property::lower_triangular);
19535 }
19536
19537 break;
19538 }
19539 default: {
19540 Assert(false,
19541 ExcMessage(
19542 std::string("Invalid H-matrix property: ") +
19543 std::string(HMatrixSupport::property_name(property))));
19544 break;
19545 }
19546 }
19547}
19548
19549
19550template <int spacedim, typename Number>
19551void
19553{
19557 this->set_current_matrix_property(M);
19558
19559 this->set_property(this->property);
19560}
19561
19562
19563template <int spacedim, typename Number>
19564void
19566 const HMatrixSupport::State state)
19567{
19568 this->state = state;
19569
19570 if (type == FullMatrixType)
19571 {
19575 switch (this->state)
19576 {
19577 case HMatrixSupport::State::matrix: {
19578 fullmatrix->set_state(LAPACKSupport::matrix);
19579
19580 break;
19581 }
19582 case HMatrixSupport::inverse_matrix: {
19583 fullmatrix->set_state(LAPACKSupport::inverse_matrix);
19584
19585 break;
19586 }
19587 case HMatrixSupport::lu: {
19588 fullmatrix->set_state(LAPACKSupport::lu);
19589
19590 break;
19591 }
19592 case HMatrixSupport::cholesky: {
19593 fullmatrix->set_state(LAPACKSupport::cholesky);
19594
19595 break;
19596 }
19597 case HMatrixSupport::eigenvalues: {
19598 fullmatrix->set_state(LAPACKSupport::eigenvalues);
19599
19600 break;
19601 }
19602 case HMatrixSupport::svd: {
19603 fullmatrix->set_state(LAPACKSupport::svd);
19604
19605 break;
19606 }
19607 case HMatrixSupport::inverse_svd: {
19608 fullmatrix->set_state(LAPACKSupport::inverse_svd);
19609
19610 break;
19611 }
19612 case HMatrixSupport::unusable: {
19613 fullmatrix->set_state(LAPACKSupport::unusable);
19614
19615 break;
19616 }
19617 default: {
19618 Assert(false,
19619 ExcMessage(
19620 std::string("Invalid H-matrix state ") +
19621 std::string(HMatrixSupport::state_name(this->state))));
19622
19623 break;
19624 }
19625 }
19626 }
19627}
19628
19629
19630template <int spacedim, typename Number>
19633{
19634 return state;
19635}
19636
19637
19638template <int spacedim, typename Number>
19639void
19641{
19642 this->set_current_matrix_state(state);
19643
19647 for (auto hmat : submatrices)
19648 {
19649 hmat->set_state(this->state);
19650 }
19651}
19652
19653
19654template <int spacedim, typename Number>
19657{
19658 return block_type;
19659}
19660
19661
19662template <int spacedim, typename Number>
19663inline void
19665 const HMatrixSupport::BlockType block_type)
19666{
19667 this->block_type = block_type;
19668}
19669
19670
19671template <int spacedim, typename Number>
19672void
19674 const HMatrixSupport::BlockType block_type)
19675{
19676 this->set_current_matrix_block_type(block_type);
19677
19678 for (unsigned int i = 0; i < submatrices.size(); i++)
19679 {
19680 switch (block_type)
19681 {
19682 case HMatrixSupport::BlockType::undefined_block: {
19687 submatrices[i]->set_block_type(block_type);
19688
19689 break;
19690 }
19691 case HMatrixSupport::BlockType::diagonal_block: {
19698 switch (i)
19699 {
19700 case 0: {
19701 submatrices[i]->set_block_type(
19702 HMatrixSupport::BlockType::diagonal_block);
19703
19704 break;
19705 }
19706 case 1: {
19707 submatrices[i]->set_block_type(
19708 HMatrixSupport::BlockType::upper_triangular_block);
19709
19710 break;
19711 }
19712 case 2: {
19713 submatrices[i]->set_block_type(
19714 HMatrixSupport::BlockType::lower_triangular_block);
19715
19716 break;
19717 }
19718 case 3: {
19719 submatrices[i]->set_block_type(
19720 HMatrixSupport::BlockType::diagonal_block);
19721
19722 break;
19723 }
19724 default: {
19725 Assert(false, ExcNotImplemented());
19726 break;
19727 }
19728 }
19729
19730 break;
19731 }
19732 case HMatrixSupport::BlockType::upper_triangular_block: {
19737 submatrices[i]->set_block_type(block_type);
19738
19739 break;
19740 }
19741 case HMatrixSupport::BlockType::lower_triangular_block: {
19746 submatrices[i]->set_block_type(block_type);
19747
19748 break;
19749 }
19750 default: {
19751 Assert(false,
19752 ExcMessage(std::string("Invalid block type ") +
19753 std::string(HMatrixSupport::block_type_name(
19754 block_type))));
19755 break;
19756 }
19757 }
19758 }
19759}
19760
19761
19762template <int spacedim, typename Number>
19765{
19766 return n;
19767}
19768
19769
19770template <int spacedim, typename Number>
19771inline RkMatrix<Number> *
19773{
19774 return rkmatrix;
19775}
19776
19777
19778template <int spacedim, typename Number>
19779inline const RkMatrix<Number> *
19781{
19782 return rkmatrix;
19783}
19784
19785
19786template <int spacedim, typename Number>
19787void
19789{
19790 switch (type)
19791 {
19793 for (HMatrix *submatrix : submatrices)
19794 {
19795 submatrix->calc_rank_upper_bound_for_rkmatrices();
19796 }
19797 }
19798
19799 break;
19800 case RkMatrixType: {
19801 this->rkmatrix->calc_rank_upper_bound();
19802 }
19803
19804 break;
19805 default: // Do nothing.
19806 {
19807 break;
19808 }
19809 }
19810}
19811
19812
19813template <int spacedim, typename Number>
19816{
19817 return fullmatrix;
19818}
19819
19820
19821template <int spacedim, typename Number>
19822inline const LAPACKFullMatrixExt<Number> *
19824{
19825 return fullmatrix;
19826}
19827
19828
19829template <int spacedim, typename Number>
19830inline std::vector<HMatrix<spacedim, Number> *> &
19832{
19833 return submatrices;
19834}
19835
19836
19837template <int spacedim, typename Number>
19838inline const std::vector<HMatrix<spacedim, Number> *> &
19840{
19841 return submatrices;
19842}
19843
19844
19845template <int spacedim, typename Number>
19846void
19848 const unsigned int precision,
19849 const bool scientific,
19850 const unsigned int width,
19851 const char *zero_string,
19852 const double denominator,
19853 const double threshold) const
19854{
19855 switch (type)
19856 {
19857 case FullMatrixType:
19858 fullmatrix->print_formatted(out,
19859 precision,
19860 scientific,
19861 width,
19862 zero_string,
19863 denominator,
19864 threshold);
19865
19866 break;
19867 case RkMatrixType:
19868 rkmatrix->print_formatted(out,
19869 precision,
19870 scientific,
19871 width,
19872 zero_string,
19873 denominator,
19874 threshold);
19875
19876 break;
19878 for (HMatrix *submatrix : submatrices)
19879 {
19880 submatrix->print_formatted(out,
19881 precision,
19882 scientific,
19883 width,
19884 zero_string,
19885 denominator,
19886 threshold);
19887 }
19888
19889 break;
19891 default:
19892 Assert(false, ExcInvalidHMatrixType(type));
19893 break;
19894 }
19895}
19896
19897
19898template <int spacedim, typename Number>
19899void
19901{
19902 print_current_matrix_info(out);
19903
19904 for (const HMatrix<spacedim, Number> *submatrix : submatrices)
19905 {
19906 submatrix->print_matrix_info(out);
19907 }
19908}
19909
19910
19911template <int spacedim, typename Number>
19912void
19914{
19915 out << "H-matrix address: " << std::hex << this << "\n";
19916 out << "Parent H-matrix address: " << std::hex << this->parent << "\n";
19917 out << "Submatrix addresses: (";
19918 for (unsigned int i = 0; i < submatrices.size(); i++)
19919 {
19920 out << std::hex << submatrices[i];
19921
19922 if (i < submatrices.size() - 1)
19923 {
19924 out << ",";
19925 }
19926 }
19927 out << ")\n";
19928 out << "Submatrix index wrt. the parent H-matrix: " << std::dec
19929 << this->submatrix_index << "\n";
19930 out << "H-matrix state: " << HMatrixSupport::state_name(this->state) << "\n"
19931 << "H-matrix property: " << HMatrixSupport::property_name(this->property)
19932 << "\n"
19933 << "H-matrix block type: "
19934 << HMatrixSupport::block_type_name(this->block_type) << std::endl;
19935
19940 print_h_submatrix_accessor(out, "M", *this);
19941 out << std::endl;
19942 out << "(#level, #Sigma_b^P, #Sigma_b^R, #Sigma_b^F)=("
19943 << bc_node->get_level() << "," << Sigma_P.size() << "," << Sigma_R.size()
19944 << "," << Sigma_F.size() << ")" << std::endl;
19945
19947 hmat_pair : Sigma_P)
19948 {
19949 out << " Sigma_P products: ";
19950 print_h_h_submatrix_mmult_accessor(
19951 out, "M1", *(hmat_pair.first), "M2", *(hmat_pair.second));
19952 }
19953}
19954
19955
19956template <int spacedim, typename Number>
19957void
19959{
19960 assign_node_ids_for_dot();
19961
19965 out << "#@startdot\n";
19966 out << "digraph hmatrix {\n";
19967
19971 out << "node [style=filled, shape=box]\n";
19972
19976 out << "\"Non-leaf block\" [fillcolor=white]\n";
19977 out << "\"Near field block\" [fillcolor=red]\n";
19978 out << "\"Far field block\" [fillcolor=green]\n";
19979
19980 _print_matrix_info_as_dot_node(out);
19981
19985 out << "}\n";
19986 out << "#@enddot" << std::endl;
19987}
19988
19989
19990template <int spacedim, typename Number>
19991void
19993 std::ostream &out,
19994 const std::string &name,
19995 const unsigned int precision,
19996 const bool scientific,
19997 const unsigned int width,
19998 const char *zero_string,
19999 const double denominator,
20000 const double threshold) const
20001{
20003 this->convertToFullMatrix(fullmat);
20004 fullmat.print_formatted_to_mat(out,
20005 name,
20006 precision,
20007 scientific,
20008 width,
20009 zero_string,
20010 denominator,
20011 threshold);
20012}
20013
20014
20015template <int spacedim, typename Number>
20016void
20018{
20023 types::global_dof_index near_field_matrix_entries_num = 0;
20024 for (auto mat : near_field_leaf_set)
20025 {
20026 Assert(mat->fullmatrix != nullptr, ExcInternalError());
20027
20028 near_field_matrix_entries_num +=
20029 mat->fullmatrix->m() * mat->fullmatrix->n();
20030 }
20031
20036 types::global_dof_index far_field_matrix_entries_num = 0;
20037 for (auto mat : far_field_leaf_set)
20038 {
20039 Assert(mat->rkmatrix != nullptr, ExcInternalError());
20040
20041 far_field_matrix_entries_num +=
20042 (mat->rkmatrix->get_m() + mat->rkmatrix->get_n()) *
20043 mat->rkmatrix->get_formal_rank();
20044 }
20045
20046 out << "Number of H-matrix nodes in the leaf set: " << leaf_set.size() << "\n"
20047 << "Number of H-matrix nodes in the near field set: "
20048 << near_field_leaf_set.size() << "\n"
20049 << "Number of H-matrix nodes in the far field set: "
20050 << far_field_leaf_set.size() << "\n"
20051 << "Number of matrix entries in the near field set: "
20052 << near_field_matrix_entries_num << "\n"
20053 << "Maximum number of matrix entries in the far field set: "
20054 << far_field_matrix_entries_num << std::endl;
20055}
20056
20057
20058template <int spacedim, typename Number>
20059void
20061{
20062 size_type current_node_id = 0;
20063
20064 std::queue<HMatrix<spacedim, Number> *> work_queue;
20065 work_queue.push(this);
20066
20067 while (!work_queue.empty())
20068 {
20069 HMatrix<spacedim, Number> *current_hmat_node = work_queue.front();
20070 work_queue.pop();
20071
20072 current_hmat_node->dot_node_id = current_node_id;
20073 current_node_id++;
20074
20079 for (auto hmat : current_hmat_node->submatrices)
20080 {
20081 work_queue.push(hmat);
20082 }
20083 }
20084}
20085
20086
20087template <int spacedim, typename Number>
20088void
20090 std::ostream &out) const
20091{
20097 out << "\"" << dot_node_id << "\""
20098 << "[label=<<b>ID: " << dot_node_id << "</b><br/>"
20099 << "tau: [" << (*row_index_range)[0] << "," << (*row_index_range)[1]
20100 << ")<br/>";
20101 out << "sigma: [" << (*col_index_range)[0] << "," << (*col_index_range)[1]
20102 << ")<br/>";
20103 out << "Level: " << bc_node->get_level() << "<br/>";
20104 out << "Parent: " << ((parent == nullptr) ? 0 : parent->dot_node_id)
20105 << "<br/>";
20106 out << "Submatrix index: " << submatrix_index << "<br/>";
20107 out << "H-matrix state: " << HMatrixSupport::state_name(state) << "<br/>"
20108 << "H-matrix property: " << HMatrixSupport::property_name(property)
20109 << "<br/>"
20110 << "H-matrix block type: " << HMatrixSupport::block_type_name(block_type)
20111 << ">,";
20112
20113 std::string node_color;
20114
20115 if (type == FullMatrixType)
20116 {
20117 node_color = "red";
20118 }
20119 else if (type == RkMatrixType)
20120 {
20121 node_color = "green";
20122 }
20123 else
20124 {
20125 node_color = "white";
20126 }
20127 out << "fillcolor = " << node_color << "]\n\n";
20128
20132 for (HMatrix<spacedim, Number> *submatrix : submatrices)
20133 {
20134 Assert(submatrix != nullptr, ExcInternalError());
20135
20136 out << "\"" << dot_node_id << "\""
20137 << "->"
20138 << "\"" << submatrix->dot_node_id << "\"\n";
20139 }
20140 out << "\n";
20141
20146 if (next_same_level_hmat_node != nullptr)
20147 {
20148 out << "\"" << dot_node_id << "\""
20149 << "->"
20150 << "\"" << next_same_level_hmat_node->dot_node_id
20151 << "\" [style=dotted]\n";
20152 }
20153
20159 if (next_same_level_same_row_hmat_node != nullptr)
20160 {
20161 out << "\"" << dot_node_id << "\""
20162 << "->"
20163 << "\"" << next_same_level_same_row_hmat_node->dot_node_id
20164 << "\" [style=solid,color=red]\n";
20165 }
20166
20167 if (previous_same_level_same_row_hmat_node != nullptr)
20168 {
20169 out << "\"" << dot_node_id << "\""
20170 << "->"
20171 << "\"" << previous_same_level_same_row_hmat_node->dot_node_id
20172 << "\" [style=dotted,color=red]\n";
20173 }
20174
20180 if (next_same_level_same_column_hmat_node != nullptr)
20181 {
20182 out << "\"" << dot_node_id << "\""
20183 << "->"
20184 << "\"" << next_same_level_same_column_hmat_node->dot_node_id
20185 << "\" [style=solid,color=green]\n";
20186 }
20187
20188 if (previous_same_level_same_column_hmat_node != nullptr)
20189 {
20190 out << "\"" << dot_node_id << "\""
20191 << "->"
20192 << "\"" << previous_same_level_same_column_hmat_node->dot_node_id
20193 << "\" [style=dotted,color=green]\n";
20194 }
20195
20199 for (HMatrix<spacedim, Number> *submatrix : submatrices)
20200 {
20201 Assert(submatrix != nullptr, ExcInternalError());
20202
20203 submatrix->_print_matrix_info_as_dot_node(out);
20204 }
20205}
20206
20207
20208template <int spacedim, typename Number>
20209void
20212{
20213 switch (property)
20214 {
20215 case HMatrixSupport::Property::general: {
20216 M.set_property(LAPACKSupport::Property::general);
20217
20218 break;
20219 }
20220 case HMatrixSupport::Property::symmetric: {
20221 M.set_property(LAPACKSupport::Property::symmetric);
20222
20223 break;
20224 }
20225 case HMatrixSupport::Property::hermite_symmetric: {
20226 M.set_property(LAPACKSupport::Property::hermite_symmetric);
20227
20228 break;
20229 }
20230 case HMatrixSupport::Property::upper_triangular: {
20231 M.set_property(LAPACKSupport::Property::upper_triangular);
20232
20233 break;
20234 }
20235 case HMatrixSupport::Property::lower_triangular: {
20236 M.set_property(LAPACKSupport::Property::lower_triangular);
20237
20238 break;
20239 }
20240 default: {
20241 Assert(false, ExcInvalidHMatrixProperty(property));
20242 break;
20243 }
20244 }
20245}
20246
20247
20248template <int spacedim, typename Number>
20249void
20251 std::ostream &out,
20252 const real_type singular_value_threshold) const
20253{
20254 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
20255
20256 const std::array<types::global_dof_index, 2> &tau_index_range =
20257 bc_node->get_data_reference()
20258 .get_tau_node()
20259 ->get_data_reference()
20260 .get_index_range();
20261 const std::array<types::global_dof_index, 2> &sigma_index_range =
20262 bc_node->get_data_reference()
20263 .get_sigma_node()
20264 ->get_data_reference()
20265 .get_index_range();
20266
20270 out << "[";
20271 print_vector_values(out, tau_index_range, " ", false);
20272 out << "),";
20273
20277 out << "[";
20278 print_vector_values(out, sigma_index_range, " ", false);
20279 out << "),";
20280
20284 out << (bc_node->get_data_reference().get_is_near_field() ? 1 : 0) << ",";
20285
20292 LAPACKFullMatrixExt<Number> copy(*fullmatrix);
20293
20294 if (copy.get_state() != LAPACKSupport::matrix)
20295 {
20296 copy.set_state(LAPACKSupport::matrix);
20297 }
20298
20299 const size_t rank = copy.rank(singular_value_threshold);
20300
20304 out << rank << "\n";
20305}
20306
20307
20308template <int spacedim, typename Number>
20309void
20311{
20312 Assert(type == RkMatrixType, ExcInvalidHMatrixType(type));
20313
20314 const std::array<types::global_dof_index, 2> &tau_index_range =
20315 bc_node->get_data_reference()
20316 .get_tau_node()
20317 ->get_data_reference()
20318 .get_index_range();
20319 const std::array<types::global_dof_index, 2> &sigma_index_range =
20320 bc_node->get_data_reference()
20321 .get_sigma_node()
20322 ->get_data_reference()
20323 .get_index_range();
20324
20328 out << "[";
20329 print_vector_values(out, tau_index_range, " ", false);
20330 out << "),";
20331
20335 out << "[";
20336 print_vector_values(out, sigma_index_range, " ", false);
20337 out << "),";
20338
20342 out << (bc_node->get_data_reference().get_is_near_field() ? 1 : 0) << ",";
20343
20347 out << rkmatrix->get_rank() << "\n";
20348}
20349
20350
20351template <int spacedim, typename Number>
20352void
20354 std::ostream &out,
20355 const real_type singular_value_threshold) const
20356{
20357 switch (type)
20358 {
20359 case FullMatrixType: {
20360 write_fullmatrix_leaf_node(out, singular_value_threshold);
20361
20362 break;
20363 }
20364 case RkMatrixType: {
20365 write_rkmatrix_leaf_node(out);
20366
20367 break;
20368 }
20370 for (HMatrix *submatrix : submatrices)
20371 {
20372 submatrix->write_leaf_set(out);
20373 }
20374
20375 break;
20376 }
20377 default: {
20378 Assert(false, ExcInvalidHMatrixType(type));
20379
20380 break;
20381 }
20382 }
20383}
20384
20385
20386template <int spacedim, typename Number>
20387void
20389 std::ostream &out,
20390 const real_type singular_value_threshold) const
20391{
20392 for (HMatrix *leaf_node : leaf_set)
20393 {
20394 switch (leaf_node->type)
20395 {
20396 case FullMatrixType: {
20397 leaf_node->write_fullmatrix_leaf_node(out,
20398 singular_value_threshold);
20399
20400 break;
20401 }
20402 case RkMatrixType: {
20403 leaf_node->write_rkmatrix_leaf_node(out);
20404
20405 break;
20406 }
20407 default: {
20408 Assert(false, ExcInvalidHMatrixType(type));
20409
20410 break;
20411 }
20412 }
20413 }
20414}
20415
20416
20417template <int spacedim, typename Number>
20420{
20425 Assert(
20426 parent != nullptr,
20427 ExcMessage(
20428 "The current H-matrix node, the diagonal block of which on a same row is to be found, should not be on the top level!"));
20429
20451 std::vector<unsigned int> submatrix_index_stack;
20452 submatrix_index_stack.reserve(this->bc_node->get_level());
20453
20454 HMatrix<spacedim, Number> *current_hmat_during_recursion = this;
20455 bool is_recursion_continued = true;
20456 while (is_recursion_continued)
20457 {
20458 if (current_hmat_during_recursion->parent == nullptr)
20459 {
20464 Assert(false, ExcInternalError());
20465 is_recursion_continued = false;
20466 }
20467 else
20468 {
20469 switch (current_hmat_during_recursion->submatrix_index)
20470 {
20471 case 1: {
20483 if (current_hmat_during_recursion->parent->submatrices[0]
20484 ->block_type ==
20485 HMatrixSupport::BlockType::diagonal_block)
20486 {
20487 current_hmat_during_recursion =
20488 current_hmat_during_recursion->parent->submatrices[0];
20489 is_recursion_continued = false;
20490 }
20491 else
20492 {
20496 submatrix_index_stack.push_back(
20497 current_hmat_during_recursion->submatrix_index);
20498 current_hmat_during_recursion =
20499 current_hmat_during_recursion->parent;
20500 }
20501
20502 break;
20503 }
20504 case 2: {
20509 if (current_hmat_during_recursion->parent->submatrices[3]
20510 ->block_type ==
20511 HMatrixSupport::BlockType::diagonal_block)
20512 {
20513 current_hmat_during_recursion =
20514 current_hmat_during_recursion->parent->submatrices[3];
20515 is_recursion_continued = false;
20516 }
20517 else
20518 {
20522 submatrix_index_stack.push_back(
20523 current_hmat_during_recursion->submatrix_index);
20524 current_hmat_during_recursion =
20525 current_hmat_during_recursion->parent;
20526 }
20527
20528 break;
20529 }
20530 default: {
20531 Assert(
20532 current_hmat_during_recursion->block_type !=
20533 HMatrixSupport::BlockType::diagonal_block,
20534 ExcMessage(
20535 "The current H-matrix node should not be a diagonal block!"));
20536
20540 submatrix_index_stack.push_back(
20541 current_hmat_during_recursion->submatrix_index);
20542 current_hmat_during_recursion =
20543 current_hmat_during_recursion->parent;
20544
20545 break;
20546 }
20547 }
20548 }
20549 }
20550
20551 const unsigned int iter_num = submatrix_index_stack.size();
20552 for (unsigned int i = 0; i < iter_num; i++)
20553 {
20554 switch (submatrix_index_stack.back())
20555 {
20556 case 0:
20557 case 1: {
20558 current_hmat_during_recursion =
20559 current_hmat_during_recursion->submatrices[0];
20560
20561 break;
20562 }
20563 case 2:
20564 case 3: {
20565 current_hmat_during_recursion =
20566 current_hmat_during_recursion->submatrices[3];
20567
20568 break;
20569 }
20570 }
20571
20572 submatrix_index_stack.pop_back();
20573 }
20574
20575 return current_hmat_during_recursion;
20576}
20577
20578
20579template <int spacedim, typename Number>
20582{
20587 Assert(
20588 parent != nullptr,
20589 ExcMessage(
20590 "The current H-matrix node, the diagonal block of which on a same row is to be found, should not be on the top level!"));
20591
20613 std::vector<unsigned int> submatrix_index_stack;
20614 submatrix_index_stack.reserve(this->bc_node->get_level());
20615
20616 HMatrix<spacedim, Number> *current_hmat_during_recursion = this;
20617 bool is_recursion_continued = true;
20618 while (is_recursion_continued)
20619 {
20620 if (current_hmat_during_recursion->parent == nullptr)
20621 {
20627 Assert(false, ExcInternalError());
20628 is_recursion_continued = false;
20629 }
20630 else
20631 {
20632 switch (current_hmat_during_recursion->submatrix_index)
20633 {
20634 case 1: {
20646 if (current_hmat_during_recursion->parent->submatrices[3]
20647 ->block_type ==
20648 HMatrixSupport::BlockType::diagonal_block)
20649 {
20650 current_hmat_during_recursion =
20651 current_hmat_during_recursion->parent->submatrices[3];
20652 is_recursion_continued = false;
20653 }
20654 else
20655 {
20659 submatrix_index_stack.push_back(
20660 current_hmat_during_recursion->submatrix_index);
20661 current_hmat_during_recursion =
20662 current_hmat_during_recursion->parent;
20663 }
20664
20665 break;
20666 }
20667 case 2: {
20672 if (current_hmat_during_recursion->parent->submatrices[0]
20673 ->block_type ==
20674 HMatrixSupport::BlockType::diagonal_block)
20675 {
20676 current_hmat_during_recursion =
20677 current_hmat_during_recursion->parent->submatrices[0];
20678 is_recursion_continued = false;
20679 }
20680 else
20681 {
20685 submatrix_index_stack.push_back(
20686 current_hmat_during_recursion->submatrix_index);
20687 current_hmat_during_recursion =
20688 current_hmat_during_recursion->parent;
20689 }
20690
20691 break;
20692 }
20693 default: {
20694 Assert(
20695 current_hmat_during_recursion->block_type !=
20696 HMatrixSupport::BlockType::diagonal_block,
20697 ExcMessage(
20698 "The current H-matrix node should not be a diagonal block!"));
20699
20703 submatrix_index_stack.push_back(
20704 current_hmat_during_recursion->submatrix_index);
20705 current_hmat_during_recursion =
20706 current_hmat_during_recursion->parent;
20707
20708 break;
20709 }
20710 }
20711 }
20712 }
20713
20714 const unsigned int iter_num = submatrix_index_stack.size();
20715 for (unsigned int i = 0; i < iter_num; i++)
20716 {
20717 switch (submatrix_index_stack.back())
20718 {
20719 case 0:
20720 case 2: {
20721 current_hmat_during_recursion =
20722 current_hmat_during_recursion->submatrices[0];
20723
20724 break;
20725 }
20726 case 1:
20727 case 3: {
20728 current_hmat_during_recursion =
20729 current_hmat_during_recursion->submatrices[3];
20730
20731 break;
20732 }
20733 }
20734
20735 submatrix_index_stack.pop_back();
20736 }
20737
20738 return current_hmat_during_recursion;
20739}
20740
20741
20742template <int spacedim, typename Number>
20743void
20745{
20746 switch (type)
20747 {
20749 for (HMatrix *submatrix : submatrices)
20750 {
20751 submatrix->truncate_to_rank(new_rank);
20752 }
20753
20754 break;
20755 }
20756 case FullMatrixType: {
20761 break;
20762 }
20763 case RkMatrixType: {
20767 rkmatrix->truncate_to_rank(new_rank);
20768
20769 break;
20770 }
20772 default: {
20773 Assert(false, ExcInvalidHMatrixType(type));
20774 break;
20775 }
20776 }
20777}
20778
20779
20780template <int spacedim, typename Number>
20781void
20783 size_type new_rank,
20784 const bool is_only_handle_tril)
20785{
20786 truncate_to_rank_diag_preserve_positive_definite(new_rank,
20787 is_only_handle_tril);
20788}
20789
20790
20791template <int spacedim, typename Number>
20792void
20794 size_type new_rank,
20795 const bool is_only_handle_tril)
20796{
20801 Assert(type == HierarchicalMatrixType, ExcInvalidHMatrixType(type));
20802 AssertDimension(submatrices.size(), 4);
20803
20808 Assert(
20809 submatrices[0]->block_type == HMatrixSupport::BlockType::diagonal_block,
20810 ExcMessage(
20811 "The first submatrix of the current H-matrix node is not a diagonal block!"));
20812 Assert(
20813 submatrices[3]->block_type == HMatrixSupport::BlockType::diagonal_block,
20814 ExcMessage(
20815 "The last submatrix of the current H-matrix node is not a diagonal block!"));
20816
20817 switch (submatrices[0]->type)
20818 {
20820 submatrices[0]->truncate_to_rank_diag_preserve_positive_definite(
20821 new_rank, is_only_handle_tril);
20822
20823 break;
20824 }
20825 case FullMatrixType: {
20829 break;
20830 }
20831 case RkMatrixType:
20835 case UndefinedMatrixType: {
20836 Assert(false, ExcInvalidHMatrixType(type));
20837 break;
20838 }
20839 }
20840
20841 switch (submatrices[3]->type)
20842 {
20844 submatrices[3]->truncate_to_rank_diag_preserve_positive_definite(
20845 new_rank, is_only_handle_tril);
20846
20847 break;
20848 }
20849 case FullMatrixType: {
20853 break;
20854 }
20855 case RkMatrixType:
20859 case UndefinedMatrixType: {
20860 Assert(false, ExcInvalidHMatrixType(type));
20861 break;
20862 }
20863 }
20864
20865 if (!is_only_handle_tril)
20866 {
20867 switch (submatrices[1]->type)
20868 {
20870 submatrices[1]
20871 ->truncate_to_rank_off_diag_preserve_positive_definite(new_rank,
20872 false);
20873
20874 break;
20875 }
20876 case RkMatrixType: {
20878 submatrices[1]->rkmatrix->truncate_to_rank(new_rank, D, C);
20879
20880 // DEBUG
20881 // std::cout << "||D||_2=" << D.frobenius_norm()
20882 // << ",||C||_2=" << C.frobenius_norm()
20883 // << std::endl;
20884
20893 break;
20894 }
20895 case FullMatrixType: {
20899 break;
20900 }
20901 case UndefinedMatrixType: {
20902 Assert(false, ExcInvalidHMatrixType(type));
20903 break;
20904 }
20905 }
20906 }
20907
20908 switch (submatrices[2]->type)
20909 {
20911 submatrices[2]->truncate_to_rank_off_diag_preserve_positive_definite(
20912 new_rank, true);
20913
20914 break;
20915 }
20916 case RkMatrixType: {
20918 submatrices[2]->rkmatrix->truncate_to_rank(new_rank, D, C);
20919
20925 submatrices[0]->addsym_diag(C);
20926 submatrices[3]->addsym_diag(D);
20927
20928 // DEBUG
20929 // std::cout << "||D||_2=" << D.frobenius_norm()
20930 // << ",||C||_2=" << C.frobenius_norm() <<
20931 // std::endl;
20932
20933 break;
20934 }
20935 case FullMatrixType: {
20939 break;
20940 }
20941 case UndefinedMatrixType: {
20942 Assert(false, ExcInvalidHMatrixType(type));
20943 break;
20944 }
20945 }
20946}
20947
20948
20949template <int spacedim, typename Number>
20950void
20952 size_type new_rank,
20953 const bool is_compensate_diag_blocks)
20954{
20959 Assert(type == HierarchicalMatrixType, ExcInvalidHMatrixType(type));
20960 AssertDimension(submatrices.size(), 4);
20961
20965 for (HMatrix *submatrix : submatrices)
20966 {
20967 switch (submatrix->type)
20968 {
20970 submatrix->truncate_to_rank_off_diag_preserve_positive_definite(
20971 new_rank, is_compensate_diag_blocks);
20972
20973 break;
20974 }
20975 case FullMatrixType: {
20979 break;
20980 }
20981 case RkMatrixType: {
20983 submatrix->rkmatrix->truncate_to_rank(new_rank, D, C);
20984
20985 if (is_compensate_diag_blocks)
20986 {
20991 HMatrix<spacedim, Number> *diag_upper_left =
20993 Assert(diag_upper_left != submatrix, ExcInternalError());
20994 Assert(diag_upper_left != nullptr, ExcInternalError());
20999 HMatrix<spacedim, Number> *diag_bottom_right =
21001 Assert(diag_bottom_right != submatrix, ExcInternalError());
21002 Assert(diag_bottom_right != nullptr, ExcInternalError());
21003
21008 diag_upper_left->addsym_diag(C);
21009 diag_bottom_right->addsym_diag(D);
21010
21011 // DEBUG
21012 // std::cout << "||D||_2=" <<
21013 // D.frobenius_norm()
21014 // << ",||C||_2=" <<
21015 // C.frobenius_norm() <<
21016 // std::endl;
21017 }
21018
21019 break;
21020 }
21021 case UndefinedMatrixType: {
21022 Assert(false, ExcInvalidHMatrixType(type));
21023 break;
21024 }
21025 }
21026 }
21027}
21028
21029
21030template <int spacedim, typename Number>
21031void
21033{
21034 if (bc_node->is_root())
21035 vmult_strategy =
21036 std::make_unique<HMatrixVmultSerialRecursive<spacedim, Number>>();
21037}
21038
21039
21040template <int spacedim, typename Number>
21041void
21043 std::unique_ptr<HMatrixVmultStrategy<spacedim, Number>> strategy)
21044{
21045 if (bc_node->is_root())
21046 vmult_strategy = std::move(strategy);
21047}
21048
21049
21050template <int spacedim, typename Number>
21051void
21053 Vector<Number> &y,
21054 const Vector<Number> &x,
21055 const HMatrixSupport::Property top_hmat_property) const
21056{
21057 vmult(y, real_type(1.0), x, top_hmat_property);
21058}
21059
21060
21061template <int spacedim, typename Number>
21062template <typename Number2>
21063void
21065 Vector<Number> &y,
21066 const Number2 alpha,
21067 const Vector<Number> &x,
21068 const HMatrixSupport::Property top_hmat_property) const
21069{
21070 static_assert(is_number_larger_or_equal<Number, Number2>());
21071 switch (type)
21072 {
21078 for (HMatrix *submatrix : submatrices)
21079 {
21080 submatrix->vmult(y, alpha, x, top_hmat_property);
21081 }
21082
21083 break;
21084 }
21085 case FullMatrixType: {
21090 switch (top_hmat_property)
21091 {
21092 case HMatrixSupport::Property::general: {
21097 Assert(property == HMatrixSupport::Property::general,
21098 ExcInvalidHMatrixProperty(property));
21099 Assert(fullmatrix->get_property() ==
21100 LAPACKSupport::Property::general,
21101 ExcInvalidLAPACKFullMatrixProperty(
21102 fullmatrix->get_property()));
21103
21104 Vector<Number> local_y(m);
21105 Vector<Number> local_x(n);
21106
21110 for (size_type j = 0; j < n; j++)
21111 {
21112 local_x(j) = x((*col_index_range)[0] + j);
21113 }
21114
21115 fullmatrix->vmult(local_y, local_x);
21116
21120 for (size_type i = 0; i < m; i++)
21121 {
21122 y((*row_index_range)[0] + i) += local_y(i) * alpha;
21123 }
21124
21125 break;
21126 }
21127 case HMatrixSupport::Property::symmetric: {
21132 switch (block_type)
21133 {
21134 case HMatrixSupport::BlockType::diagonal_block: {
21140 Assert(property ==
21141 HMatrixSupport::Property::symmetric,
21142 ExcInvalidHMatrixProperty(property));
21147 Assert(fullmatrix->get_property() ==
21148 LAPACKSupport::Property::symmetric,
21149 ExcInvalidLAPACKFullMatrixProperty(
21150 fullmatrix->get_property()));
21151
21159 Vector<Number> local_y(m);
21160 Vector<Number> local_x(n);
21161
21165 for (size_type j = 0; j < n; j++)
21166 {
21167 local_x(j) = x((*col_index_range)[0] + j);
21168 }
21169
21170 fullmatrix->vmult(local_y, local_x);
21171
21175 for (size_type i = 0; i < m; i++)
21176 {
21177 y((*row_index_range)[0] + i) +=
21178 alpha * local_y(i);
21179 }
21180
21181 break;
21182 }
21183 case HMatrixSupport::BlockType::
21184 lower_triangular_block: {
21199 Assert(property == HMatrixSupport::Property::general,
21200 ExcInvalidHMatrixProperty(property));
21201 Assert(fullmatrix->get_property() ==
21202 LAPACKSupport::Property::general,
21203 ExcInvalidLAPACKFullMatrixProperty(
21204 fullmatrix->get_property()));
21205
21206 Vector<Number> local_y(m);
21207 Vector<Number> local_x(n);
21208
21212 for (size_type j = 0; j < n; j++)
21213 {
21214 local_x(j) = x((*col_index_range)[0] + j);
21215 }
21216
21217 fullmatrix->vmult(local_y, local_x);
21218
21222 for (size_type i = 0; i < m; i++)
21223 {
21224 y((*row_index_range)[0] + i) +=
21225 alpha * local_y(i);
21226 }
21227
21228 Vector<Number> local_y_for_Tvmult(n);
21229 Vector<Number> local_x_for_Tvmult(m);
21230
21235 for (size_type i = 0; i < m; i++)
21236 {
21237 local_x_for_Tvmult(i) =
21238 x((*row_index_range)[0] + i);
21239 }
21240
21241 fullmatrix->Tvmult(local_y_for_Tvmult,
21242 local_x_for_Tvmult);
21243
21248 for (size_type j = 0; j < n; j++)
21249 {
21250 y((*col_index_range)[0] + j) +=
21251 alpha * local_y_for_Tvmult(j);
21252 }
21253
21254 break;
21255 }
21256 case HMatrixSupport::BlockType::
21257 upper_triangular_block: {
21262 break;
21263 }
21264 default: {
21265 Assert(false, ExcInvalidHMatrixBlockType(block_type));
21266
21267 break;
21268 }
21269 }
21270
21271 break;
21272 }
21273 case HMatrixSupport::Property::hermite_symmetric: {
21279 switch (block_type)
21280 {
21281 case HMatrixSupport::BlockType::diagonal_block: {
21287 Assert(property ==
21288 HMatrixSupport::Property::hermite_symmetric,
21289 ExcInvalidHMatrixProperty(property));
21294 Assert(fullmatrix->get_property() ==
21295 LAPACKSupport::Property::hermite_symmetric,
21296 ExcInvalidLAPACKFullMatrixProperty(
21297 fullmatrix->get_property()));
21298
21306 Vector<Number> local_y(m);
21307 Vector<Number> local_x(n);
21308
21312 for (size_type j = 0; j < n; j++)
21313 {
21314 local_x(j) = x((*col_index_range)[0] + j);
21315 }
21316
21317 fullmatrix->vmult(local_y, local_x);
21318
21322 for (size_type i = 0; i < m; i++)
21323 {
21324 y((*row_index_range)[0] + i) +=
21325 alpha * local_y(i);
21326 }
21327
21328 break;
21329 }
21330 case HMatrixSupport::BlockType::
21331 lower_triangular_block: {
21345 Assert(property == HMatrixSupport::Property::general,
21346 ExcInvalidHMatrixProperty(property));
21347 Assert(fullmatrix->get_property() ==
21348 LAPACKSupport::Property::general,
21349 ExcInvalidLAPACKFullMatrixProperty(
21350 fullmatrix->get_property()));
21351
21352 Vector<Number> local_y(m);
21353 Vector<Number> local_x(n);
21354
21358 for (size_type j = 0; j < n; j++)
21359 {
21360 local_x(j) = x((*col_index_range)[0] + j);
21361 }
21362
21363 fullmatrix->vmult(local_y, local_x);
21364
21368 for (size_type i = 0; i < m; i++)
21369 {
21370 y((*row_index_range)[0] + i) +=
21371 alpha * local_y(i);
21372 }
21373
21374 Vector<Number> local_y_for_Hvmult(n);
21375 Vector<Number> local_x_for_Hvmult(m);
21376
21381 for (size_type i = 0; i < m; i++)
21382 {
21383 local_x_for_Hvmult(i) =
21384 x((*row_index_range)[0] + i);
21385 }
21386
21387 fullmatrix->Hvmult(local_y_for_Hvmult,
21388 local_x_for_Hvmult);
21389
21394 for (size_type j = 0; j < n; j++)
21395 {
21396 y((*col_index_range)[0] + j) +=
21397 alpha * local_y_for_Hvmult(j);
21398 }
21399
21400 break;
21401 }
21402 case HMatrixSupport::BlockType::
21403 upper_triangular_block: {
21411 break;
21412 }
21413 default: {
21414 throw(ExcInvalidHMatrixBlockType(block_type));
21415
21416 break;
21417 }
21418 }
21419
21420 break;
21421 }
21422 case HMatrixSupport::Property::lower_triangular: {
21428 switch (block_type)
21429 {
21430 case HMatrixSupport::BlockType::diagonal_block: {
21436 Assert(property ==
21437 HMatrixSupport::Property::lower_triangular,
21438 ExcInvalidHMatrixProperty(property));
21443 Assert(fullmatrix->get_property() ==
21444 LAPACKSupport::Property::lower_triangular,
21445 ExcInvalidLAPACKFullMatrixProperty(
21446 fullmatrix->get_property()));
21447
21453 Vector<Number> local_y(m);
21454 Vector<Number> local_x(n);
21455
21459 for (size_type j = 0; j < n; j++)
21460 {
21461 local_x(j) = x((*col_index_range)[0] + j);
21462 }
21463
21464 fullmatrix->vmult(local_y, local_x);
21465
21469 for (size_type i = 0; i < m; i++)
21470 {
21471 y((*row_index_range)[0] + i) +=
21472 alpha * local_y(i);
21473 }
21474
21475 break;
21476 }
21477 case HMatrixSupport::BlockType::
21478 lower_triangular_block: {
21485 Assert(property == HMatrixSupport::Property::general,
21486 ExcInvalidHMatrixProperty(property));
21487 Assert(fullmatrix->get_property() ==
21488 LAPACKSupport::Property::general,
21489 ExcInvalidLAPACKFullMatrixProperty(
21490 fullmatrix->get_property()));
21491
21492 Vector<Number> local_y(m);
21493 Vector<Number> local_x(n);
21494
21498 for (size_type j = 0; j < n; j++)
21499 {
21500 local_x(j) = x((*col_index_range)[0] + j);
21501 }
21502
21503 fullmatrix->vmult(local_y, local_x);
21504
21508 for (size_type i = 0; i < m; i++)
21509 {
21510 y((*row_index_range)[0] + i) +=
21511 alpha * local_y(i);
21512 }
21513
21514 break;
21515 }
21516 case HMatrixSupport::BlockType::
21517 upper_triangular_block: {
21523 break;
21524 }
21525 default: {
21526 throw(ExcInvalidHMatrixBlockType(block_type));
21527
21528 break;
21529 }
21530 }
21531
21532 break;
21533 }
21534 case HMatrixSupport::Property::upper_triangular: {
21540 switch (block_type)
21541 {
21542 case HMatrixSupport::BlockType::diagonal_block: {
21548 Assert(property ==
21549 HMatrixSupport::Property::upper_triangular,
21550 ExcInvalidHMatrixProperty(property));
21555 Assert(fullmatrix->get_property() ==
21556 LAPACKSupport::Property::upper_triangular,
21557 ExcInvalidLAPACKFullMatrixProperty(
21558 fullmatrix->get_property()));
21559
21564 Vector<Number> local_y(m);
21565 Vector<Number> local_x(n);
21566
21570 for (size_type j = 0; j < n; j++)
21571 {
21572 local_x(j) = x((*col_index_range)[0] + j);
21573 }
21574
21575 fullmatrix->vmult(local_y, local_x);
21576
21580 for (size_type i = 0; i < m; i++)
21581 {
21582 y((*row_index_range)[0] + i) +=
21583 alpha * local_y(i);
21584 }
21585
21586 break;
21587 }
21588 case HMatrixSupport::BlockType::
21589 lower_triangular_block: {
21594 break;
21595 }
21596 case HMatrixSupport::BlockType::
21597 upper_triangular_block: {
21604 Assert(property == HMatrixSupport::Property::general,
21605 ExcInvalidHMatrixProperty(property));
21606 Assert(fullmatrix->get_property() ==
21607 LAPACKSupport::Property::general,
21608 ExcInvalidLAPACKFullMatrixProperty(
21609 fullmatrix->get_property()));
21610
21611 Vector<Number> local_y(m);
21612 Vector<Number> local_x(n);
21613
21617 for (size_type j = 0; j < n; j++)
21618 {
21619 local_x(j) = x((*col_index_range)[0] + j);
21620 }
21621
21622 fullmatrix->vmult(local_y, local_x);
21623
21627 for (size_type i = 0; i < m; i++)
21628 {
21629 y((*row_index_range)[0] + i) +=
21630 alpha * local_y(i);
21631 }
21632
21633 break;
21634 }
21635 default: {
21636 throw(ExcInvalidHMatrixBlockType(block_type));
21637
21638 break;
21639 }
21640 }
21641
21642 break;
21643 }
21644 default: {
21645 throw(ExcInvalidHMatrixProperty(top_hmat_property));
21646
21647 break;
21648 }
21649 }
21650
21651 break;
21652 }
21653 case RkMatrixType: {
21658 switch (top_hmat_property)
21659 {
21660 case HMatrixSupport::Property::general: {
21665 Assert(property == HMatrixSupport::Property::general,
21666 ExcInvalidHMatrixProperty(property));
21667
21668 Vector<Number> local_y(m);
21669 Vector<Number> local_x(n);
21670
21674 for (size_type j = 0; j < n; j++)
21675 {
21676 local_x(j) = x((*col_index_range)[0] + j);
21677 }
21678
21679 rkmatrix->vmult(local_y, local_x);
21680
21684 for (size_type i = 0; i < m; i++)
21685 {
21686 y((*row_index_range)[0] + i) += alpha * local_y(i);
21687 }
21688
21689 break;
21690 }
21691 case HMatrixSupport::Property::symmetric: {
21696 switch (block_type)
21697 {
21698 case HMatrixSupport::BlockType::diagonal_block: {
21703 throw(ExcInvalidHMatrixBlockType(block_type));
21704
21705 break;
21706 }
21707 case HMatrixSupport::BlockType::
21708 lower_triangular_block: {
21723 Assert(property == HMatrixSupport::Property::general,
21724 ExcInvalidHMatrixProperty(property));
21725
21726 Vector<Number> local_y(m);
21727 Vector<Number> local_x(n);
21728
21732 for (size_type j = 0; j < n; j++)
21733 {
21734 local_x(j) = x((*col_index_range)[0] + j);
21735 }
21736
21737 rkmatrix->vmult(local_y, local_x);
21738
21742 for (size_type i = 0; i < m; i++)
21743 {
21744 y((*row_index_range)[0] + i) +=
21745 alpha * local_y(i);
21746 }
21747
21748 Vector<Number> local_y_for_Tvmult(n);
21749 Vector<Number> local_x_for_Tvmult(m);
21750
21755 for (size_type i = 0; i < m; i++)
21756 {
21757 local_x_for_Tvmult(i) =
21758 x((*row_index_range)[0] + i);
21759 }
21760
21761 rkmatrix->Tvmult(local_y_for_Tvmult,
21762 local_x_for_Tvmult);
21763
21768 for (size_type j = 0; j < n; j++)
21769 {
21770 y((*col_index_range)[0] + j) +=
21771 alpha * local_y_for_Tvmult(j);
21772 }
21773
21774 break;
21775 }
21776 case HMatrixSupport::BlockType::
21777 upper_triangular_block: {
21782 break;
21783 }
21784 default: {
21785 throw(ExcInvalidHMatrixBlockType(block_type));
21786
21787 break;
21788 }
21789 }
21790
21791 break;
21792 }
21793 case HMatrixSupport::Property::hermite_symmetric: {
21799 switch (block_type)
21800 {
21801 case HMatrixSupport::BlockType::diagonal_block: {
21806 throw(ExcInvalidHMatrixBlockType(block_type));
21807
21808 break;
21809 }
21810 case HMatrixSupport::BlockType::
21811 lower_triangular_block: {
21825 Assert(property == HMatrixSupport::Property::general,
21826 ExcInvalidHMatrixProperty(property));
21827
21828 Vector<Number> local_y(m);
21829 Vector<Number> local_x(n);
21830
21834 for (size_type j = 0; j < n; j++)
21835 {
21836 local_x(j) = x((*col_index_range)[0] + j);
21837 }
21838
21839 rkmatrix->vmult(local_y, local_x);
21840
21844 for (size_type i = 0; i < m; i++)
21845 {
21846 y((*row_index_range)[0] + i) +=
21847 alpha * local_y(i);
21848 }
21849
21850 Vector<Number> local_y_for_Hvmult(n);
21851 Vector<Number> local_x_for_Hvmult(m);
21852
21857 for (size_type i = 0; i < m; i++)
21858 {
21859 local_x_for_Hvmult(i) =
21860 x((*row_index_range)[0] + i);
21861 }
21862
21863 rkmatrix->Hvmult(local_y_for_Hvmult,
21864 local_x_for_Hvmult);
21865
21870 for (size_type j = 0; j < n; j++)
21871 {
21872 y((*col_index_range)[0] + j) +=
21873 alpha * local_y_for_Hvmult(j);
21874 }
21875
21876 break;
21877 }
21878 case HMatrixSupport::BlockType::
21879 upper_triangular_block: {
21884 break;
21885 }
21886 default: {
21887 throw(ExcInvalidHMatrixBlockType(block_type));
21888
21889 break;
21890 }
21891 }
21892
21893 break;
21894 }
21895 case HMatrixSupport::Property::lower_triangular: {
21901 switch (block_type)
21902 {
21903 case HMatrixSupport::BlockType::diagonal_block: {
21908 throw(ExcInvalidHMatrixBlockType(block_type));
21909
21910 break;
21911 }
21912 case HMatrixSupport::BlockType::
21913 lower_triangular_block: {
21920 Assert(property == HMatrixSupport::Property::general,
21921 ExcInvalidHMatrixProperty(property));
21922
21923 Vector<Number> local_y(m);
21924 Vector<Number> local_x(n);
21925
21929 for (size_type j = 0; j < n; j++)
21930 {
21931 local_x(j) = x((*col_index_range)[0] + j);
21932 }
21933
21934 rkmatrix->vmult(local_y, local_x);
21935
21939 for (size_type i = 0; i < m; i++)
21940 {
21941 y((*row_index_range)[0] + i) +=
21942 alpha * local_y(i);
21943 }
21944
21945 break;
21946 }
21947 case HMatrixSupport::BlockType::
21948 upper_triangular_block: {
21953 break;
21954 }
21955 default: {
21956 throw(ExcInvalidHMatrixBlockType(block_type));
21957
21958 break;
21959 }
21960 }
21961
21962 break;
21963 }
21964 case HMatrixSupport::Property::upper_triangular: {
21970 switch (block_type)
21971 {
21972 case HMatrixSupport::BlockType::diagonal_block: {
21977 throw(ExcInvalidHMatrixBlockType(block_type));
21978
21979 break;
21980 }
21981 case HMatrixSupport::BlockType::
21982 lower_triangular_block: {
21987 break;
21988 }
21989 case HMatrixSupport::BlockType::
21990 upper_triangular_block: {
21997 Assert(property == HMatrixSupport::Property::general,
21998 ExcInvalidHMatrixProperty(property));
21999
22000 Vector<Number> local_y(m);
22001 Vector<Number> local_x(n);
22002
22006 for (size_type j = 0; j < n; j++)
22007 {
22008 local_x(j) = x((*col_index_range)[0] + j);
22009 }
22010
22011 rkmatrix->vmult(local_y, local_x);
22012
22016 for (size_type i = 0; i < m; i++)
22017 {
22018 y((*row_index_range)[0] + i) +=
22019 alpha * local_y(i);
22020 }
22021
22022 break;
22023 }
22024 default: {
22025 throw(ExcInvalidHMatrixBlockType(block_type));
22026
22027 break;
22028 }
22029 }
22030
22031 break;
22032 }
22033 default: {
22034 throw(ExcInvalidHMatrixProperty(top_hmat_property));
22035
22036 break;
22037 }
22038 }
22039
22040 break;
22041 }
22043 default: {
22044 Assert(false, ExcInvalidHMatrixType(type));
22045 break;
22046 }
22047 }
22048}
22049
22050
22051template <int spacedim, typename Number>
22052void
22054 Vector<Number> &y,
22055 const Vector<Number> &x,
22056 const HMatrix<spacedim, Number> &starting_hmat,
22057 const HMatrixSupport::Property top_hmat_property) const
22058{
22059 vmult(y, real_type(1.0), x, starting_hmat, top_hmat_property);
22060}
22061
22062
22063template <int spacedim, typename Number>
22064template <typename Number2>
22065void
22067 Vector<Number> &y,
22068 const Number2 alpha,
22069 const Vector<Number> &x,
22070 const HMatrix<spacedim, Number> &starting_hmat,
22071 const HMatrixSupport::Property top_hmat_property) const
22072{
22073 static_assert(is_number_larger_or_equal<Number, Number2>());
22074 switch (type)
22075 {
22081 for (HMatrix *submatrix : submatrices)
22082 {
22083 submatrix->vmult(y, alpha, x, starting_hmat, top_hmat_property);
22084 }
22085
22086 break;
22087 }
22088 case FullMatrixType: {
22093 switch (top_hmat_property)
22094 {
22095 case HMatrixSupport::Property::general: {
22100 Assert(property == HMatrixSupport::Property::general,
22101 ExcInvalidHMatrixProperty(property));
22102 Assert(fullmatrix->get_property() ==
22103 LAPACKSupport::Property::general,
22104 ExcInvalidLAPACKFullMatrixProperty(
22105 fullmatrix->get_property()));
22106
22107 Vector<Number> local_y(m);
22108 Vector<Number> local_x(n);
22109
22113 for (size_type j = 0; j < n; j++)
22114 {
22115 local_x(j) = x((*col_index_range)[0] -
22116 (*starting_hmat.col_index_range)[0] + j);
22117 }
22118
22119 fullmatrix->vmult(local_y, local_x);
22120
22124 for (size_type i = 0; i < m; i++)
22125 {
22126 y((*row_index_range)[0] -
22127 (*starting_hmat.row_index_range)[0] + i) +=
22128 alpha * local_y(i);
22129 }
22130
22131 break;
22132 }
22133 case HMatrixSupport::Property::symmetric: {
22138 switch (block_type)
22139 {
22140 case HMatrixSupport::BlockType::diagonal_block: {
22146 Assert(property ==
22147 HMatrixSupport::Property::symmetric,
22148 ExcInvalidHMatrixProperty(property));
22153 Assert(fullmatrix->get_property() ==
22154 LAPACKSupport::Property::symmetric,
22155 ExcInvalidLAPACKFullMatrixProperty(
22156 fullmatrix->get_property()));
22157
22165 Vector<Number> local_y(m);
22166 Vector<Number> local_x(n);
22167
22171 for (size_type j = 0; j < n; j++)
22172 {
22173 local_x(j) =
22174 x((*col_index_range)[0] -
22175 (*starting_hmat.col_index_range)[0] + j);
22176 }
22177
22178 fullmatrix->vmult(local_y, local_x);
22179
22183 for (size_type i = 0; i < m; i++)
22184 {
22185 y((*row_index_range)[0] -
22186 (*starting_hmat.row_index_range)[0] + i) +=
22187 alpha * local_y(i);
22188 }
22189
22190 break;
22191 }
22192 case HMatrixSupport::BlockType::
22193 lower_triangular_block: {
22208 Assert(property == HMatrixSupport::Property::general,
22209 ExcInvalidHMatrixProperty(property));
22210 Assert(fullmatrix->get_property() ==
22211 LAPACKSupport::Property::general,
22212 ExcInvalidLAPACKFullMatrixProperty(
22213 fullmatrix->get_property()));
22214
22215 Vector<Number> local_y(m);
22216 Vector<Number> local_x(n);
22217
22221 for (size_type j = 0; j < n; j++)
22222 {
22223 local_x(j) =
22224 x((*col_index_range)[0] -
22225 (*starting_hmat.col_index_range)[0] + j);
22226 }
22227
22228 fullmatrix->vmult(local_y, local_x);
22229
22233 for (size_type i = 0; i < m; i++)
22234 {
22235 y((*row_index_range)[0] -
22236 (*starting_hmat.row_index_range)[0] + i) +=
22237 alpha * local_y(i);
22238 }
22239
22240 Vector<Number> local_y_for_Tvmult(n);
22241 Vector<Number> local_x_for_Tvmult(m);
22242
22247 for (size_type i = 0; i < m; i++)
22248 {
22249 local_x_for_Tvmult(i) =
22250 x((*row_index_range)[0] -
22251 (*starting_hmat.row_index_range)[0] + i);
22252 }
22253
22254 fullmatrix->Tvmult(local_y_for_Tvmult,
22255 local_x_for_Tvmult);
22256
22261 for (size_type j = 0; j < n; j++)
22262 {
22263 y((*col_index_range)[0] -
22264 (*starting_hmat.col_index_range)[0] + j) +=
22265 alpha * local_y_for_Tvmult(j);
22266 }
22267
22268 break;
22269 }
22270 case HMatrixSupport::BlockType::
22271 upper_triangular_block: {
22276 break;
22277 }
22278 default: {
22279 throw(ExcInvalidHMatrixBlockType(block_type));
22280
22281 break;
22282 }
22283 }
22284
22285 break;
22286 }
22287 case HMatrixSupport::Property::hermite_symmetric: {
22293 switch (block_type)
22294 {
22295 case HMatrixSupport::BlockType::diagonal_block: {
22301 Assert(property ==
22302 HMatrixSupport::Property::hermite_symmetric,
22303 ExcInvalidHMatrixProperty(property));
22308 Assert(fullmatrix->get_property() ==
22309 LAPACKSupport::Property::hermite_symmetric,
22310 ExcInvalidLAPACKFullMatrixProperty(
22311 fullmatrix->get_property()));
22312
22320 Vector<Number> local_y(m);
22321 Vector<Number> local_x(n);
22322
22326 for (size_type j = 0; j < n; j++)
22327 {
22328 local_x(j) =
22329 x((*col_index_range)[0] -
22330 (*starting_hmat.col_index_range)[0] + j);
22331 }
22332
22333 fullmatrix->vmult(local_y, local_x);
22334
22338 for (size_type i = 0; i < m; i++)
22339 {
22340 y((*row_index_range)[0] -
22341 (*starting_hmat.row_index_range)[0] + i) +=
22342 alpha * local_y(i);
22343 }
22344
22345 break;
22346 }
22347 case HMatrixSupport::BlockType::
22348 lower_triangular_block: {
22362 Assert(property == HMatrixSupport::Property::general,
22363 ExcInvalidHMatrixProperty(property));
22364 Assert(fullmatrix->get_property() ==
22365 LAPACKSupport::Property::general,
22366 ExcInvalidLAPACKFullMatrixProperty(
22367 fullmatrix->get_property()));
22368
22369 Vector<Number> local_y(m);
22370 Vector<Number> local_x(n);
22371
22375 for (size_type j = 0; j < n; j++)
22376 {
22377 local_x(j) =
22378 x((*col_index_range)[0] -
22379 (*starting_hmat.col_index_range)[0] + j);
22380 }
22381
22382 fullmatrix->vmult(local_y, local_x);
22383
22387 for (size_type i = 0; i < m; i++)
22388 {
22389 y((*row_index_range)[0] -
22390 (*starting_hmat.row_index_range)[0] + i) +=
22391 alpha * local_y(i);
22392 }
22393
22394 Vector<Number> local_y_for_Hvmult(n);
22395 Vector<Number> local_x_for_Hvmult(m);
22396
22401 for (size_type i = 0; i < m; i++)
22402 {
22403 local_x_for_Hvmult(i) =
22404 x((*row_index_range)[0] -
22405 (*starting_hmat.row_index_range)[0] + i);
22406 }
22407
22408 fullmatrix->Hvmult(local_y_for_Hvmult,
22409 local_x_for_Hvmult);
22410
22415 for (size_type j = 0; j < n; j++)
22416 {
22417 y((*col_index_range)[0] -
22418 (*starting_hmat.col_index_range)[0] + j) +=
22419 alpha * local_y_for_Hvmult(j);
22420 }
22421
22422 break;
22423 }
22424 case HMatrixSupport::BlockType::
22425 upper_triangular_block: {
22430 break;
22431 }
22432 default: {
22433 throw(ExcInvalidHMatrixBlockType(block_type));
22434
22435 break;
22436 }
22437 }
22438
22439 break;
22440 }
22441 case HMatrixSupport::Property::lower_triangular: {
22447 switch (block_type)
22448 {
22449 case HMatrixSupport::BlockType::diagonal_block: {
22455 Assert(property ==
22456 HMatrixSupport::Property::lower_triangular,
22457 ExcInvalidHMatrixProperty(property));
22462 Assert(fullmatrix->get_property() ==
22463 LAPACKSupport::Property::lower_triangular,
22464 ExcInvalidLAPACKFullMatrixProperty(
22465 fullmatrix->get_property()));
22466
22472 Vector<Number> local_y(m);
22473 Vector<Number> local_x(n);
22474
22478 for (size_type j = 0; j < n; j++)
22479 {
22480 local_x(j) =
22481 x((*col_index_range)[0] -
22482 (*starting_hmat.col_index_range)[0] + j);
22483 }
22484
22485 fullmatrix->vmult(local_y, local_x);
22486
22490 for (size_type i = 0; i < m; i++)
22491 {
22492 y((*row_index_range)[0] -
22493 (*starting_hmat.row_index_range)[0] + i) +=
22494 alpha * local_y(i);
22495 }
22496
22497 break;
22498 }
22499 case HMatrixSupport::BlockType::
22500 lower_triangular_block: {
22507 Assert(property == HMatrixSupport::Property::general,
22508 ExcInvalidHMatrixProperty(property));
22509 Assert(fullmatrix->get_property() ==
22510 LAPACKSupport::Property::general,
22511 ExcInvalidLAPACKFullMatrixProperty(
22512 fullmatrix->get_property()));
22513
22514 Vector<Number> local_y(m);
22515 Vector<Number> local_x(n);
22516
22520 for (size_type j = 0; j < n; j++)
22521 {
22522 local_x(j) =
22523 x((*col_index_range)[0] -
22524 (*starting_hmat.col_index_range)[0] + j);
22525 }
22526
22527 fullmatrix->vmult(local_y, local_x);
22528
22532 for (size_type i = 0; i < m; i++)
22533 {
22534 y((*row_index_range)[0] -
22535 (*starting_hmat.row_index_range)[0] + i) +=
22536 alpha * local_y(i);
22537 }
22538
22539 break;
22540 }
22541 case HMatrixSupport::BlockType::
22542 upper_triangular_block: {
22548 break;
22549 }
22550 default: {
22551 throw(ExcInvalidHMatrixBlockType(block_type));
22552
22553 break;
22554 }
22555 }
22556
22557 break;
22558 }
22559 case HMatrixSupport::Property::upper_triangular: {
22565 switch (block_type)
22566 {
22567 case HMatrixSupport::BlockType::diagonal_block: {
22573 Assert(property ==
22574 HMatrixSupport::Property::upper_triangular,
22575 ExcInvalidHMatrixProperty(property));
22580 Assert(fullmatrix->get_property() ==
22581 LAPACKSupport::Property::upper_triangular,
22582 ExcInvalidLAPACKFullMatrixProperty(
22583 fullmatrix->get_property()));
22584
22589 Vector<Number> local_y(m);
22590 Vector<Number> local_x(n);
22591
22595 for (size_type j = 0; j < n; j++)
22596 {
22597 local_x(j) =
22598 x((*col_index_range)[0] -
22599 (*starting_hmat.col_index_range)[0] + j);
22600 }
22601
22602 fullmatrix->vmult(local_y, local_x);
22603
22607 for (size_type i = 0; i < m; i++)
22608 {
22609 y((*row_index_range)[0] -
22610 (*starting_hmat.row_index_range)[0] + i) +=
22611 alpha * local_y(i);
22612 }
22613
22614 break;
22615 }
22616 case HMatrixSupport::BlockType::
22617 lower_triangular_block: {
22622 break;
22623 }
22624 case HMatrixSupport::BlockType::
22625 upper_triangular_block: {
22632 Assert(property == HMatrixSupport::Property::general,
22633 ExcInvalidHMatrixProperty(property));
22634 Assert(fullmatrix->get_property() ==
22635 LAPACKSupport::Property::general,
22636 ExcInvalidLAPACKFullMatrixProperty(
22637 fullmatrix->get_property()));
22638
22639 Vector<Number> local_y(m);
22640 Vector<Number> local_x(n);
22641
22645 for (size_type j = 0; j < n; j++)
22646 {
22647 local_x(j) =
22648 x((*col_index_range)[0] -
22649 (*starting_hmat.col_index_range)[0] + j);
22650 }
22651
22652 fullmatrix->vmult(local_y, local_x);
22653
22657 for (size_type i = 0; i < m; i++)
22658 {
22659 y((*row_index_range)[0] -
22660 (*starting_hmat.row_index_range)[0] + i) +=
22661 alpha * local_y(i);
22662 }
22663
22664 break;
22665 }
22666 default: {
22667 throw(ExcInvalidHMatrixBlockType(block_type));
22668
22669 break;
22670 }
22671 }
22672
22673 break;
22674 }
22675 default: {
22676 throw(ExcInvalidHMatrixProperty(top_hmat_property));
22677
22678 break;
22679 }
22680 }
22681
22682 break;
22683 }
22684 case RkMatrixType: {
22689 switch (top_hmat_property)
22690 {
22691 case HMatrixSupport::Property::general: {
22696 Assert(property == HMatrixSupport::Property::general,
22697 ExcInvalidHMatrixProperty(property));
22698
22699 Vector<Number> local_y(m);
22700 Vector<Number> local_x(n);
22701
22705 for (size_type j = 0; j < n; j++)
22706 {
22707 local_x(j) = x((*col_index_range)[0] -
22708 (*starting_hmat.col_index_range)[0] + j);
22709 }
22710
22711 rkmatrix->vmult(local_y, local_x);
22712
22716 for (size_type i = 0; i < m; i++)
22717 {
22718 y((*row_index_range)[0] -
22719 (*starting_hmat.row_index_range)[0] + i) +=
22720 alpha * local_y(i);
22721 }
22722
22723 break;
22724 }
22725 case HMatrixSupport::Property::symmetric: {
22730 switch (block_type)
22731 {
22732 case HMatrixSupport::BlockType::diagonal_block: {
22737 Assert(false, ExcInvalidHMatrixBlockType(block_type));
22738
22739 break;
22740 }
22741 case HMatrixSupport::BlockType::
22742 lower_triangular_block: {
22757 Assert(property == HMatrixSupport::Property::general,
22758 ExcInvalidHMatrixProperty(property));
22759
22760 Vector<Number> local_y(m);
22761 Vector<Number> local_x(n);
22762
22766 for (size_type j = 0; j < n; j++)
22767 {
22768 local_x(j) =
22769 x((*col_index_range)[0] -
22770 (*starting_hmat.col_index_range)[0] + j);
22771 }
22772
22773 rkmatrix->vmult(local_y, local_x);
22774
22778 for (size_type i = 0; i < m; i++)
22779 {
22780 y((*row_index_range)[0] -
22781 (*starting_hmat.row_index_range)[0] + i) +=
22782 alpha * local_y(i);
22783 }
22784
22785 Vector<Number> local_y_for_Tvmult(n);
22786 Vector<Number> local_x_for_Tvmult(m);
22787
22792 for (size_type i = 0; i < m; i++)
22793 {
22794 local_x_for_Tvmult(i) =
22795 x((*row_index_range)[0] -
22796 (*starting_hmat.row_index_range)[0] + i);
22797 }
22798
22799 rkmatrix->Tvmult(local_y_for_Tvmult,
22800 local_x_for_Tvmult);
22801
22806 for (size_type j = 0; j < n; j++)
22807 {
22808 y((*col_index_range)[0] -
22809 (*starting_hmat.col_index_range)[0] + j) +=
22810 alpha * local_y_for_Tvmult(j);
22811 }
22812
22813 break;
22814 }
22815 case HMatrixSupport::BlockType::
22816 upper_triangular_block: {
22821 break;
22822 }
22823 default: {
22824 throw(ExcInvalidHMatrixBlockType(block_type));
22825
22826 break;
22827 }
22828 }
22829
22830 break;
22831 }
22832 case HMatrixSupport::Property::hermite_symmetric: {
22838 switch (block_type)
22839 {
22840 case HMatrixSupport::BlockType::diagonal_block: {
22845 Assert(false, ExcInvalidHMatrixBlockType(block_type));
22846
22847 break;
22848 }
22849 case HMatrixSupport::BlockType::
22850 lower_triangular_block: {
22864 Assert(property == HMatrixSupport::Property::general,
22865 ExcInvalidHMatrixProperty(property));
22866
22867 Vector<Number> local_y(m);
22868 Vector<Number> local_x(n);
22869
22873 for (size_type j = 0; j < n; j++)
22874 {
22875 local_x(j) =
22876 x((*col_index_range)[0] -
22877 (*starting_hmat.col_index_range)[0] + j);
22878 }
22879
22880 rkmatrix->vmult(local_y, local_x);
22881
22885 for (size_type i = 0; i < m; i++)
22886 {
22887 y((*row_index_range)[0] -
22888 (*starting_hmat.row_index_range)[0] + i) +=
22889 alpha * local_y(i);
22890 }
22891
22892 Vector<Number> local_y_for_Hvmult(n);
22893 Vector<Number> local_x_for_Hvmult(m);
22894
22899 for (size_type i = 0; i < m; i++)
22900 {
22901 local_x_for_Hvmult(i) =
22902 x((*row_index_range)[0] -
22903 (*starting_hmat.row_index_range)[0] + i);
22904 }
22905
22906 rkmatrix->Hvmult(local_y_for_Hvmult,
22907 local_x_for_Hvmult);
22908
22913 for (size_type j = 0; j < n; j++)
22914 {
22915 y((*col_index_range)[0] -
22916 (*starting_hmat.col_index_range)[0] + j) +=
22917 alpha * local_y_for_Hvmult(j);
22918 }
22919
22920 break;
22921 }
22922 case HMatrixSupport::BlockType::
22923 upper_triangular_block: {
22928 break;
22929 }
22930 default: {
22931 throw(ExcInvalidHMatrixBlockType(block_type));
22932
22933 break;
22934 }
22935 }
22936
22937 break;
22938 }
22939 case HMatrixSupport::Property::lower_triangular: {
22945 switch (block_type)
22946 {
22947 case HMatrixSupport::BlockType::diagonal_block: {
22952 throw(ExcInvalidHMatrixBlockType(block_type));
22953
22954 break;
22955 }
22956 case HMatrixSupport::BlockType::
22957 lower_triangular_block: {
22964 Assert(property == HMatrixSupport::Property::general,
22965 ExcInvalidHMatrixProperty(property));
22966
22967 Vector<Number> local_y(m);
22968 Vector<Number> local_x(n);
22969
22973 for (size_type j = 0; j < n; j++)
22974 {
22975 local_x(j) =
22976 x((*col_index_range)[0] -
22977 (*starting_hmat.col_index_range)[0] + j);
22978 }
22979
22980 rkmatrix->vmult(local_y, local_x);
22981
22985 for (size_type i = 0; i < m; i++)
22986 {
22987 y((*row_index_range)[0] -
22988 (*starting_hmat.row_index_range)[0] + i) +=
22989 alpha * local_y(i);
22990 }
22991
22992 break;
22993 }
22994 case HMatrixSupport::BlockType::
22995 upper_triangular_block: {
23000 break;
23001 }
23002 default: {
23003 throw(ExcInvalidHMatrixBlockType(block_type));
23004
23005 break;
23006 }
23007 }
23008
23009 break;
23010 }
23011 case HMatrixSupport::Property::upper_triangular: {
23017 switch (block_type)
23018 {
23019 case HMatrixSupport::BlockType::diagonal_block: {
23024 throw(ExcInvalidHMatrixBlockType(block_type));
23025
23026 break;
23027 }
23028 case HMatrixSupport::BlockType::
23029 lower_triangular_block: {
23034 break;
23035 }
23036 case HMatrixSupport::BlockType::
23037 upper_triangular_block: {
23044 Assert(property == HMatrixSupport::Property::general,
23045 ExcInvalidHMatrixProperty(property));
23046
23047 Vector<Number> local_y(m);
23048 Vector<Number> local_x(n);
23049
23053 for (size_type j = 0; j < n; j++)
23054 {
23055 local_x(j) =
23056 x((*col_index_range)[0] -
23057 (*starting_hmat.col_index_range)[0] + j);
23058 }
23059
23060 rkmatrix->vmult(local_y, local_x);
23061
23065 for (size_type i = 0; i < m; i++)
23066 {
23067 y((*row_index_range)[0] -
23068 (*starting_hmat.row_index_range)[0] + i) +=
23069 alpha * local_y(i);
23070 }
23071
23072 break;
23073 }
23074 default: {
23075 throw(ExcInvalidHMatrixBlockType(block_type));
23076
23077 break;
23078 }
23079 }
23080
23081 break;
23082 }
23083 default: {
23084 throw(ExcInvalidHMatrixProperty(top_hmat_property));
23085
23086 break;
23087 }
23088 }
23089
23090 break;
23091 }
23093 default: {
23094 Assert(false, ExcInvalidHMatrixType(type));
23095 break;
23096 }
23097 }
23098}
23099
23100
23101template <int spacedim, typename Number>
23102template <typename Number2, typename Number3>
23103void
23105 Vector<Number> &y,
23106 const Number3 alpha,
23107 const Vector<Number> &x) const
23108{
23109 static_assert(is_number_larger_or_equal<Number, Number2>());
23110 static_assert(is_number_larger_or_equal<Number, Number3>());
23114 Assert(parent == nullptr, ExcInternalError());
23115
23119 y *= beta;
23120
23124 for (size_type l = 0; l < leaf_set.size(); l++)
23125 {
23126 const size_type m = this->leaf_set[l]->m;
23127 const size_type n = this->leaf_set[l]->n;
23128
23133 Vector<Number> local_y(m);
23134 Vector<Number> local_x(n);
23135
23139 for (size_type j = 0; j < n; j++)
23140 {
23141 local_x(j) = x((*this->leaf_set[l]->col_index_range)[0] + j);
23142 }
23143
23144 switch (this->leaf_set[l]->type)
23145 {
23147 this->leaf_set[l]->fullmatrix->vmult(local_y, local_x);
23148
23149 break;
23150 }
23152 this->leaf_set[l]->rkmatrix->vmult(local_y, local_x);
23153
23154 break;
23155 }
23156 default: {
23157 Assert(false, ExcInvalidHMatrixType(this->leaf_set[l]->type));
23158
23159 break;
23160 }
23161 }
23162
23166 for (size_type i = 0; i < m; i++)
23167 {
23168 y((*this->leaf_set[l]->row_index_range)[0] + i) += alpha * local_y(i);
23169 }
23170
23171 if (this->property == HMatrixSupport::Property::symmetric &&
23172 this->leaf_set[l]->block_type ==
23173 HMatrixSupport::BlockType::lower_triangular_block)
23174 {
23181 Vector<Number> local_y_for_Tvmult(n);
23182 Vector<Number> local_x_for_Tvmult(m);
23183
23188 for (size_type i = 0; i < m; i++)
23189 {
23190 local_x_for_Tvmult(i) =
23191 x((*this->leaf_set[l]->row_index_range)[0] + i);
23192 }
23193
23194 switch (this->leaf_set[l]->type)
23195 {
23197 this->leaf_set[l]->fullmatrix->Tvmult(local_y_for_Tvmult,
23198 local_x_for_Tvmult);
23199
23200 break;
23201 }
23203 this->leaf_set[l]->rkmatrix->Tvmult(local_y_for_Tvmult,
23204 local_x_for_Tvmult);
23205
23206 break;
23207 }
23208 default: {
23209 Assert(false, ExcInvalidHMatrixType(this->leaf_set[l]->type));
23210
23211 break;
23212 }
23213 }
23214
23219 for (size_type j = 0; j < n; j++)
23220 {
23221 y((*this->leaf_set[l]->col_index_range)[0] + j) +=
23222 alpha * local_y_for_Tvmult(j);
23223 }
23224 }
23225 else if (this->property == HMatrixSupport::Property::hermite_symmetric &&
23226 this->leaf_set[l]->block_type ==
23227 HMatrixSupport::BlockType::lower_triangular_block)
23228 {
23235 Vector<Number> local_y_for_Hvmult(n);
23236 Vector<Number> local_x_for_Hvmult(m);
23237
23242 for (size_type i = 0; i < m; i++)
23243 {
23244 local_x_for_Hvmult(i) =
23245 x((*this->leaf_set[l]->row_index_range)[0] + i);
23246 }
23247
23248 switch (this->leaf_set[l]->type)
23249 {
23251 this->leaf_set[l]->fullmatrix->Hvmult(local_y_for_Hvmult,
23252 local_x_for_Hvmult);
23253
23254 break;
23255 }
23257 this->leaf_set[l]->rkmatrix->Hvmult(local_y_for_Hvmult,
23258 local_x_for_Hvmult);
23259
23260 break;
23261 }
23262 default: {
23263 Assert(false, ExcInvalidHMatrixType(this->leaf_set[l]->type));
23264
23265 break;
23266 }
23267 }
23268
23273 for (size_type j = 0; j < n; j++)
23274 {
23275 y((*this->leaf_set[l]->col_index_range)[0] + j) +=
23276 alpha * local_y_for_Hvmult(j);
23277 }
23278 }
23279 }
23280}
23281
23282
23283template <int spacedim, typename Number>
23284template <typename Number2, typename Number3>
23285void
23287 Vector<Number> &y,
23288 const Number3 alpha,
23289 const Vector<Number> &x) const
23290{
23291 static_assert(is_number_larger_or_equal<Number, Number2>());
23292 static_assert(is_number_larger_or_equal<Number, Number3>());
23296 Assert(parent == nullptr, ExcInternalError());
23297
23298 const unsigned int thread_num = data_for_vmult_or_tvmult_threads->size();
23299
23304 if (thread_num > 1)
23305 {
23306 // Set OpenBLAS num threads to 1 when task parallelization is used.
23307 const int blas_num_threads = openblas_get_num_threads();
23308 openblas_set_num_threads(1);
23309
23315 auto local_scale_and_multiplication =
23316 [this, beta, alpha, &y, &x](const unsigned int thread_no) -> void {
23320 for (size_type i = (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23321 .vmult_result_index_range[0];
23322 i < (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23323 .vmult_result_index_range[1];
23324 i++)
23325 {
23326 y[i] *= beta;
23327 }
23328
23332 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23333 .local_vmult_result = Number(0.);
23334 if (this->property == HMatrixSupport::Property::symmetric ||
23335 this->property == HMatrixSupport::Property::hermite_symmetric)
23336 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23337 .local_tvmult_result = Number(0.);
23338
23343 for (size_type l = (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23344 .leaf_set_interval.first;
23345 l <= (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23346 .leaf_set_interval.second;
23347 l++)
23348 {
23349 const size_type m = this->leaf_set[l]->m;
23350 const size_type n = this->leaf_set[l]->n;
23351
23356 Vector<Number> local_y(m);
23357 Vector<Number> local_x(n);
23358
23362 for (size_type j = 0; j < n; j++)
23363 {
23364 local_x(j) = x((*this->leaf_set[l]->col_index_range)[0] + j);
23365 }
23366
23367 switch (this->leaf_set[l]->type)
23368 {
23370 this->leaf_set[l]->fullmatrix->vmult(local_y, local_x);
23371
23372 break;
23373 }
23375 this->leaf_set[l]->rkmatrix->vmult(local_y, local_x);
23376
23377 break;
23378 }
23379 default: {
23380 Assert(false,
23381 ExcInvalidHMatrixType(this->leaf_set[l]->type));
23382
23383 break;
23384 }
23385 }
23386
23392 for (size_type i = 0; i < m; i++)
23393 {
23394 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23395 .local_vmult_result(
23396 (*this->leaf_set[l]->row_index_range)[0] -
23397 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23398 .local_vmult_result_index_range[0] +
23399 i) += alpha * local_y(i);
23400 }
23401
23402 if (this->property == HMatrixSupport::Property::symmetric &&
23403 this->leaf_set[l]->block_type ==
23404 HMatrixSupport::BlockType::lower_triangular_block)
23405 {
23412 Vector<Number> local_y_for_Tvmult(n);
23413 Vector<Number> local_x_for_Tvmult(m);
23414
23418 for (size_type i = 0; i < m; i++)
23419 {
23420 local_x_for_Tvmult(i) =
23421 x((*this->leaf_set[l]->row_index_range)[0] + i);
23422 }
23423
23424 switch (this->leaf_set[l]->type)
23425 {
23427 this->leaf_set[l]->fullmatrix->Tvmult(
23428 local_y_for_Tvmult, local_x_for_Tvmult);
23429
23430 break;
23431 }
23433 this->leaf_set[l]->rkmatrix->Tvmult(local_y_for_Tvmult,
23434 local_x_for_Tvmult);
23435
23436 break;
23437 }
23438 default: {
23439 Assert(false,
23440 ExcInvalidHMatrixType(this->leaf_set[l]->type));
23441
23442 break;
23443 }
23444 }
23445
23451 for (size_type j = 0; j < n; j++)
23452 {
23453 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23454 .local_tvmult_result(
23455 (*this->leaf_set[l]->col_index_range)[0] -
23456 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23457 .local_tvmult_result_index_range[0] +
23458 j) += alpha * local_y_for_Tvmult(j);
23459 }
23460 }
23461 else if (this->property ==
23462 HMatrixSupport::Property::hermite_symmetric &&
23463 this->leaf_set[l]->block_type ==
23464 HMatrixSupport::BlockType::lower_triangular_block)
23465 {
23472 Vector<Number> local_y_for_Hvmult(n);
23473 Vector<Number> local_x_for_Hvmult(m);
23474
23478 for (size_type i = 0; i < m; i++)
23479 {
23480 local_x_for_Hvmult(i) =
23481 x((*this->leaf_set[l]->row_index_range)[0] + i);
23482 }
23483
23484 switch (this->leaf_set[l]->type)
23485 {
23487 this->leaf_set[l]->fullmatrix->Hvmult(
23488 local_y_for_Hvmult, local_x_for_Hvmult);
23489
23490 break;
23491 }
23493 this->leaf_set[l]->rkmatrix->Hvmult(local_y_for_Hvmult,
23494 local_x_for_Hvmult);
23495
23496 break;
23497 }
23498 default: {
23499 Assert(false,
23500 ExcInvalidHMatrixType(this->leaf_set[l]->type));
23501
23502 break;
23503 }
23504 }
23505
23511 for (size_type j = 0; j < n; j++)
23512 {
23513 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23514 .local_tvmult_result(
23515 (*this->leaf_set[l]->col_index_range)[0] -
23516 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23517 .local_tvmult_result_index_range[0] +
23518 j) += alpha * local_y_for_Hvmult(j);
23519 }
23520 }
23521 }
23522 };
23523
23524 Threads::TaskGroup<void> local_scaling_and_multiplication_tasks;
23525 for (unsigned int i = 0; i < thread_num; i++)
23526 {
23527 local_scaling_and_multiplication_tasks +=
23528 Threads::new_task(std::bind(local_scale_and_multiplication, i));
23529 }
23530
23531 local_scaling_and_multiplication_tasks.join_all();
23532
23533 auto assemble_contribution_from_all_threads =
23534 [this, &y](const unsigned int thread_no) -> void {
23535 unsigned int other_thread_no = 0;
23536 for (const auto &range_intersection :
23537 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23538 .vmult_result_index_ranges_contributed_from_other_threads)
23539 {
23540 for (size_type i = range_intersection[0]; i < range_intersection[1];
23541 i++)
23542 {
23543 y(i) +=
23544 (*this->data_for_vmult_or_tvmult_threads)[other_thread_no]
23545 .local_vmult_result(
23546 i -
23547 (*this->data_for_vmult_or_tvmult_threads)[other_thread_no]
23548 .local_vmult_result_index_range[0]);
23549 }
23550
23551 other_thread_no++;
23552 }
23553
23554 if (this->property == HMatrixSupport::Property::symmetric ||
23555 this->property == HMatrixSupport::Property::hermite_symmetric)
23556 {
23562 unsigned int other_thread_no = 0;
23563 for (const auto &range_intersection :
23564 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
23565 .tvmult_result_index_ranges_contributed_from_other_threads)
23566 {
23567 for (size_type i = range_intersection[0];
23568 i < range_intersection[1];
23569 i++)
23570 {
23571 y(i) +=
23572 (*this->data_for_vmult_or_tvmult_threads)[other_thread_no]
23573 .local_tvmult_result(
23574 i - (*this->data_for_vmult_or_tvmult_threads)
23575 [other_thread_no]
23576 .local_tvmult_result_index_range[0]);
23577 }
23578
23579 other_thread_no++;
23580 }
23581 }
23582 };
23583
23584 Threads::TaskGroup<void> assembly_tasks;
23585 for (unsigned int i = 0; i < thread_num; i++)
23586 {
23587 assembly_tasks += Threads::new_task(
23588 std::bind(assemble_contribution_from_all_threads, i));
23589 }
23590
23591 assembly_tasks.join_all();
23592
23593 // Restore the original OpenBLAS num threads.
23594 openblas_set_num_threads(blas_num_threads);
23595 }
23596 else
23597 {
23598 vmult_serial_iterative(beta, y, alpha, x);
23599 }
23600}
23601
23602
23603template <int spacedim, typename Number>
23604void
23606 const Vector<Number> &x) const
23607{
23608 if (!vmult_strategy)
23609 {
23610 Assert(false, ExcInternalError());
23611 }
23612 else
23613 vmult_strategy->vmult(y, *this, x);
23614}
23615
23616
23617template <int spacedim, typename Number>
23618void
23620 const Vector<Number> &x) const
23621{
23622 if (!vmult_strategy)
23623 {
23624 Assert(false, ExcInternalError());
23625 }
23626 else
23627 vmult_strategy->vmult_add(y, *this, x);
23628}
23629
23630
23631template <int spacedim, typename Number>
23632template <typename Number2>
23633void
23635 const Number2 alpha,
23636 const Vector<Number> &x) const
23637{
23638 if (!vmult_strategy)
23639 {
23640 Assert(false, ExcInternalError());
23641 }
23642 else
23643 vmult_strategy->vmult(y, alpha, *this, x);
23644}
23645
23646
23647template <int spacedim, typename Number>
23648template <typename Number2>
23649void
23651 const Number2 alpha,
23652 const Vector<Number> &x) const
23653{
23654 if (!vmult_strategy)
23655 {
23656 Assert(false, ExcInternalError());
23657 }
23658 else
23659 vmult_strategy->vmult_add(y, alpha, *this, x);
23660}
23661
23662
23663template <int spacedim, typename Number>
23664void
23666 Vector<Number> &y,
23667 const Vector<Number> &x,
23668 const HMatrixSupport::Property top_hmat_property) const
23669{
23670 Tvmult(y, real_type(1.0), x, top_hmat_property);
23671}
23672
23673
23674template <int spacedim, typename Number>
23675template <typename Number2>
23676void
23678 Vector<Number> &y,
23679 const Number2 alpha,
23680 const Vector<Number> &x,
23681 const HMatrixSupport::Property top_hmat_property) const
23682{
23683 static_assert(is_number_larger_or_equal<Number, Number2>());
23684 switch (type)
23685 {
23691 for (HMatrix *submatrix : submatrices)
23692 {
23693 submatrix->Tvmult(y, alpha, x, top_hmat_property);
23694 }
23695
23696 break;
23697 }
23698 case FullMatrixType: {
23703 switch (top_hmat_property)
23704 {
23705 case HMatrixSupport::Property::general: {
23710 Assert(property == HMatrixSupport::Property::general,
23711 ExcInvalidHMatrixProperty(property));
23712 Assert(fullmatrix->get_property() ==
23713 LAPACKSupport::Property::general,
23714 ExcInvalidLAPACKFullMatrixProperty(
23715 fullmatrix->get_property()));
23716
23717 Vector<Number> local_y(n);
23718 Vector<Number> local_x(m);
23719
23723 for (size_type j = 0; j < m; j++)
23724 {
23725 local_x(j) = x((*row_index_range)[0] + j);
23726 }
23727
23728 fullmatrix->Tvmult(local_y, local_x);
23729
23733 for (size_type i = 0; i < n; i++)
23734 {
23735 y((*col_index_range)[0] + i) += alpha * local_y(i);
23736 }
23737
23738 break;
23739 }
23740 case HMatrixSupport::Property::symmetric: {
23745 switch (block_type)
23746 {
23747 case HMatrixSupport::BlockType::diagonal_block: {
23753 Assert(property ==
23754 HMatrixSupport::Property::symmetric,
23755 ExcInvalidHMatrixProperty(property));
23760 Assert(fullmatrix->get_property() ==
23761 LAPACKSupport::Property::symmetric,
23762 ExcInvalidLAPACKFullMatrixProperty(
23763 fullmatrix->get_property()));
23764
23772 Vector<Number> local_y(n);
23773 Vector<Number> local_x(m);
23774
23778 for (size_type j = 0; j < m; j++)
23779 {
23780 local_x(j) = x((*row_index_range)[0] + j);
23781 }
23782
23783 fullmatrix->Tvmult(local_y, local_x);
23784
23788 for (size_type i = 0; i < n; i++)
23789 {
23790 y((*col_index_range)[0] + i) +=
23791 alpha * local_y(i);
23792 }
23793
23794 break;
23795 }
23796 case HMatrixSupport::BlockType::
23797 lower_triangular_block: {
23810 Assert(property == HMatrixSupport::Property::general,
23811 ExcInvalidHMatrixProperty(property));
23812 Assert(fullmatrix->get_property() ==
23813 LAPACKSupport::Property::general,
23814 ExcInvalidLAPACKFullMatrixProperty(
23815 fullmatrix->get_property()));
23816
23817 Vector<Number> local_y(n);
23818 Vector<Number> local_x(m);
23819
23823 for (size_type j = 0; j < m; j++)
23824 {
23825 local_x(j) = x((*row_index_range)[0] + j);
23826 }
23827
23828 fullmatrix->Tvmult(local_y, local_x);
23829
23833 for (size_type i = 0; i < n; i++)
23834 {
23835 y((*col_index_range)[0] + i) +=
23836 alpha * local_y(i);
23837 }
23838
23839 Vector<Number> local_y_for_vmult(m);
23840 Vector<Number> local_x_for_vmult(n);
23841
23845 for (size_type j = 0; j < n; j++)
23846 {
23847 local_x_for_vmult(j) =
23848 x((*col_index_range)[0] + j);
23849 }
23850
23851 fullmatrix->vmult(local_y_for_vmult,
23852 local_x_for_vmult);
23853
23857 for (size_type i = 0; i < m; i++)
23858 {
23859 y((*row_index_range)[0] + i) +=
23860 alpha * local_y_for_vmult(i);
23861 }
23862
23863 break;
23864 }
23865 case HMatrixSupport::BlockType::
23866 upper_triangular_block: {
23874 break;
23875 }
23876 default: {
23877 throw(ExcInvalidHMatrixBlockType(block_type));
23878
23879 break;
23880 }
23881 }
23882
23883 break;
23884 }
23885 case HMatrixSupport::Property::hermite_symmetric: {
23891 switch (block_type)
23892 {
23893 case HMatrixSupport::BlockType::diagonal_block: {
23899 Assert(property ==
23900 HMatrixSupport::Property::hermite_symmetric,
23901 ExcInvalidHMatrixProperty(property));
23906 Assert(fullmatrix->get_property() ==
23907 LAPACKSupport::Property::hermite_symmetric,
23908 ExcInvalidLAPACKFullMatrixProperty(
23909 fullmatrix->get_property()));
23910
23918 Vector<Number> local_y(n);
23919 Vector<Number> local_x(m);
23920
23924 for (size_type j = 0; j < m; j++)
23925 {
23926 local_x(j) = x((*row_index_range)[0] + j);
23927 }
23928
23929 fullmatrix->Tvmult(local_y, local_x);
23930
23934 for (size_type i = 0; i < n; i++)
23935 {
23936 y((*col_index_range)[0] + i) +=
23937 alpha * local_y(i);
23938 }
23939
23940 break;
23941 }
23942 case HMatrixSupport::BlockType::
23943 lower_triangular_block: {
23957 Assert(property == HMatrixSupport::Property::general,
23958 ExcInvalidHMatrixProperty(property));
23959 Assert(fullmatrix->get_property() ==
23960 LAPACKSupport::Property::general,
23961 ExcInvalidLAPACKFullMatrixProperty(
23962 fullmatrix->get_property()));
23963
23964 Vector<Number> local_y(n);
23965 Vector<Number> local_x(m);
23966
23970 for (size_type j = 0; j < m; j++)
23971 {
23972 local_x(j) = x((*row_index_range)[0] + j);
23973 }
23974
23975 fullmatrix->Tvmult(local_y, local_x);
23976
23980 for (size_type i = 0; i < n; i++)
23981 {
23982 y((*col_index_range)[0] + i) +=
23983 alpha * local_y(i);
23984 }
23985
23986 Vector<Number> local_y_for_vmult(m);
23987 Vector<Number> local_x_for_vmult(n);
23988
23992 for (size_type j = 0; j < n; j++)
23993 {
23994 local_x_for_vmult(j) =
23995 x((*col_index_range)[0] + j);
23996 }
23997
23998 fullmatrix->Cvmult(local_y_for_vmult,
23999 local_x_for_vmult);
24000
24004 for (size_type i = 0; i < m; i++)
24005 {
24006 y((*row_index_range)[0] + i) +=
24007 alpha * local_y_for_vmult(i);
24008 }
24009
24010 break;
24011 }
24012 case HMatrixSupport::BlockType::
24013 upper_triangular_block: {
24021 break;
24022 }
24023 default: {
24024 throw(ExcInvalidHMatrixBlockType(block_type));
24025
24026 break;
24027 }
24028 }
24029
24030 break;
24031 }
24032 case HMatrixSupport::Property::lower_triangular: {
24038 switch (block_type)
24039 {
24040 case HMatrixSupport::BlockType::diagonal_block: {
24046 Assert(property ==
24047 HMatrixSupport::Property::lower_triangular,
24048 ExcInvalidHMatrixProperty(property));
24053 Assert(fullmatrix->get_property() ==
24054 LAPACKSupport::Property::lower_triangular,
24055 ExcInvalidLAPACKFullMatrixProperty(
24056 fullmatrix->get_property()));
24057
24062 Vector<Number> local_y(n);
24063 Vector<Number> local_x(m);
24064
24068 for (size_type j = 0; j < m; j++)
24069 {
24070 local_x(j) = x((*row_index_range)[0] + j);
24071 }
24072
24073 fullmatrix->Tvmult(local_y, local_x);
24074
24078 for (size_type i = 0; i < n; i++)
24079 {
24080 y((*col_index_range)[0] + i) +=
24081 alpha * local_y(i);
24082 }
24083
24084 break;
24085 }
24086 case HMatrixSupport::BlockType::
24087 lower_triangular_block: {
24093 Assert(property == HMatrixSupport::Property::general,
24094 ExcInvalidHMatrixProperty(property));
24095 Assert(fullmatrix->get_property() ==
24096 LAPACKSupport::Property::general,
24097 ExcInvalidLAPACKFullMatrixProperty(
24098 fullmatrix->get_property()));
24099
24100 Vector<Number> local_y(n);
24101 Vector<Number> local_x(m);
24102
24106 for (size_type j = 0; j < m; j++)
24107 {
24108 local_x(j) = x((*row_index_range)[0] + j);
24109 }
24110
24111 fullmatrix->Tvmult(local_y, local_x);
24112
24116 for (size_type i = 0; i < n; i++)
24117 {
24118 y((*col_index_range)[0] + i) +=
24119 alpha * local_y(i);
24120 }
24121
24122 break;
24123 }
24124 case HMatrixSupport::BlockType::
24125 upper_triangular_block: {
24132 break;
24133 }
24134 default: {
24135 throw(ExcInvalidHMatrixBlockType(block_type));
24136
24137 break;
24138 }
24139 }
24140
24141 break;
24142 }
24143 case HMatrixSupport::Property::upper_triangular: {
24149 switch (block_type)
24150 {
24151 case HMatrixSupport::BlockType::diagonal_block: {
24157 Assert(property ==
24158 HMatrixSupport::Property::upper_triangular,
24159 ExcInvalidHMatrixProperty(property));
24164 Assert(fullmatrix->get_property() ==
24165 LAPACKSupport::Property::upper_triangular,
24166 ExcInvalidLAPACKFullMatrixProperty(
24167 fullmatrix->get_property()));
24168
24173 Vector<Number> local_y(n);
24174 Vector<Number> local_x(m);
24175
24179 for (size_type j = 0; j < m; j++)
24180 {
24181 local_x(j) = x((*row_index_range)[0] + j);
24182 }
24183
24184 fullmatrix->Tvmult(local_y, local_x);
24185
24189 for (size_type i = 0; i < n; i++)
24190 {
24191 y((*col_index_range)[0] + i) +=
24192 alpha * local_y(i);
24193 }
24194
24195 break;
24196 }
24197 case HMatrixSupport::BlockType::
24198 upper_triangular_block: {
24204 Assert(property == HMatrixSupport::Property::general,
24205 ExcInvalidHMatrixProperty(property));
24206 Assert(fullmatrix->get_property() ==
24207 LAPACKSupport::Property::general,
24208 ExcInvalidLAPACKFullMatrixProperty(
24209 fullmatrix->get_property()));
24210
24211 Vector<Number> local_y(n);
24212 Vector<Number> local_x(m);
24213
24217 for (size_type j = 0; j < m; j++)
24218 {
24219 local_x(j) = x((*row_index_range)[0] + j);
24220 }
24221
24222 fullmatrix->Tvmult(local_y, local_x);
24223
24227 for (size_type i = 0; i < n; i++)
24228 {
24229 y((*col_index_range)[0] + i) +=
24230 alpha * local_y(i);
24231 }
24232
24233 break;
24234 }
24235 case HMatrixSupport::BlockType::
24236 lower_triangular_block: {
24241 break;
24242 }
24243 default: {
24244 throw(ExcInvalidHMatrixBlockType(block_type));
24245
24246 break;
24247 }
24248 }
24249
24250 break;
24251 }
24252 default: {
24253 throw(ExcInvalidHMatrixProperty(top_hmat_property));
24254
24255 break;
24256 }
24257 }
24258
24259 break;
24260 }
24261 case RkMatrixType: {
24266 switch (top_hmat_property)
24267 {
24268 case HMatrixSupport::Property::general: {
24273 Assert(property == HMatrixSupport::Property::general,
24274 ExcInvalidHMatrixProperty(property));
24275
24276 Vector<Number> local_y(n);
24277 Vector<Number> local_x(m);
24278
24282 for (size_type j = 0; j < m; j++)
24283 {
24284 local_x(j) = x((*row_index_range)[0] + j);
24285 }
24286
24287 rkmatrix->Tvmult(local_y, local_x);
24288
24292 for (size_type i = 0; i < n; i++)
24293 {
24294 y((*col_index_range)[0] + i) += alpha * local_y(i);
24295 }
24296
24297 break;
24298 }
24299 case HMatrixSupport::Property::symmetric: {
24304 switch (block_type)
24305 {
24306 case HMatrixSupport::BlockType::diagonal_block: {
24311 throw(ExcInvalidHMatrixBlockType(block_type));
24312
24313 break;
24314 }
24315 case HMatrixSupport::BlockType::
24316 lower_triangular_block: {
24329 Assert(property == HMatrixSupport::Property::general,
24330 ExcInvalidHMatrixProperty(property));
24331
24332 Vector<Number> local_y(n);
24333 Vector<Number> local_x(m);
24334
24338 for (size_type j = 0; j < m; j++)
24339 {
24340 local_x(j) = x((*row_index_range)[0] + j);
24341 }
24342
24343 rkmatrix->Tvmult(local_y, local_x);
24344
24348 for (size_type i = 0; i < n; i++)
24349 {
24350 y((*col_index_range)[0] + i) +=
24351 alpha * local_y(i);
24352 }
24353
24354 Vector<Number> local_y_for_vmult(m);
24355 Vector<Number> local_x_for_vmult(n);
24356
24360 for (size_type j = 0; j < n; j++)
24361 {
24362 local_x_for_vmult(j) =
24363 x((*col_index_range)[0] + j);
24364 }
24365
24366 rkmatrix->vmult(local_y_for_vmult, local_x_for_vmult);
24367
24371 for (size_type i = 0; i < m; i++)
24372 {
24373 y((*row_index_range)[0] + i) +=
24374 alpha * local_y_for_vmult(i);
24375 }
24376
24377 break;
24378 }
24379 case HMatrixSupport::BlockType::
24380 upper_triangular_block: {
24385 break;
24386 }
24387 default: {
24388 throw(ExcInvalidHMatrixBlockType(block_type));
24389
24390 break;
24391 }
24392 }
24393
24394 break;
24395 }
24396 case HMatrixSupport::Property::hermite_symmetric: {
24402 switch (block_type)
24403 {
24404 case HMatrixSupport::BlockType::diagonal_block: {
24409 throw(ExcInvalidHMatrixBlockType(block_type));
24410
24411 break;
24412 }
24413 case HMatrixSupport::BlockType::
24414 lower_triangular_block: {
24427 Assert(property == HMatrixSupport::Property::general,
24428 ExcInvalidHMatrixProperty(property));
24429
24430 Vector<Number> local_y(n);
24431 Vector<Number> local_x(m);
24432
24436 for (size_type j = 0; j < m; j++)
24437 {
24438 local_x(j) = x((*row_index_range)[0] + j);
24439 }
24440
24441 rkmatrix->Tvmult(local_y, local_x);
24442
24446 for (size_type i = 0; i < n; i++)
24447 {
24448 y((*col_index_range)[0] + i) +=
24449 alpha * local_y(i);
24450 }
24451
24452 Vector<Number> local_y_for_vmult(m);
24453 Vector<Number> local_x_for_vmult(n);
24454
24458 for (size_type j = 0; j < n; j++)
24459 {
24460 local_x_for_vmult(j) =
24461 x((*col_index_range)[0] + j);
24462 }
24463
24464 rkmatrix->Cvmult(local_y_for_vmult,
24465 local_x_for_vmult);
24466
24470 for (size_type i = 0; i < m; i++)
24471 {
24472 y((*row_index_range)[0] + i) +=
24473 alpha * local_y_for_vmult(i);
24474 }
24475
24476 break;
24477 }
24478 case HMatrixSupport::BlockType::
24479 upper_triangular_block: {
24484 break;
24485 }
24486 default: {
24487 throw(ExcInvalidHMatrixBlockType(block_type));
24488
24489 break;
24490 }
24491 }
24492
24493 break;
24494 }
24495 case HMatrixSupport::Property::lower_triangular: {
24501 switch (block_type)
24502 {
24503 case HMatrixSupport::BlockType::diagonal_block: {
24508 throw(ExcInvalidHMatrixBlockType(block_type));
24509
24510 break;
24511 }
24512 case HMatrixSupport::BlockType::
24513 lower_triangular_block: {
24519 Assert(property == HMatrixSupport::Property::general,
24520 ExcInvalidHMatrixProperty(property));
24521
24522 Vector<Number> local_y(n);
24523 Vector<Number> local_x(m);
24524
24528 for (size_type j = 0; j < m; j++)
24529 {
24530 local_x(j) = x((*row_index_range)[0] + j);
24531 }
24532
24533 rkmatrix->Tvmult(local_y, local_x);
24534
24538 for (size_type i = 0; i < n; i++)
24539 {
24540 y((*col_index_range)[0] + i) +=
24541 alpha * local_y(i);
24542 }
24543
24544 break;
24545 }
24546 case HMatrixSupport::BlockType::
24547 upper_triangular_block: {
24552 break;
24553 }
24554 default: {
24555 throw(ExcInvalidHMatrixBlockType(block_type));
24556
24557 break;
24558 }
24559 }
24560
24561 break;
24562 }
24563 case HMatrixSupport::Property::upper_triangular: {
24569 switch (block_type)
24570 {
24571 case HMatrixSupport::BlockType::diagonal_block: {
24576 throw(ExcInvalidHMatrixBlockType(block_type));
24577
24578 break;
24579 }
24580 case HMatrixSupport::BlockType::
24581 upper_triangular_block: {
24587 Assert(property == HMatrixSupport::Property::general,
24588 ExcInvalidHMatrixProperty(property));
24589
24590 Vector<Number> local_y(n);
24591 Vector<Number> local_x(m);
24592
24596 for (size_type j = 0; j < m; j++)
24597 {
24598 local_x(j) = x((*row_index_range)[0] + j);
24599 }
24600
24601 rkmatrix->Tvmult(local_y, local_x);
24602
24606 for (size_type i = 0; i < n; i++)
24607 {
24608 y((*col_index_range)[0] + i) +=
24609 alpha * local_y(i);
24610 }
24611
24612 break;
24613 }
24614 case HMatrixSupport::BlockType::
24615 lower_triangular_block: {
24620 break;
24621 }
24622 default: {
24623 throw(ExcInvalidHMatrixBlockType(block_type));
24624
24625 break;
24626 }
24627 }
24628
24629 break;
24630 }
24631 default: {
24632 throw(ExcInvalidHMatrixProperty(top_hmat_property));
24633
24634 break;
24635 }
24636 }
24637
24638 break;
24639 }
24641 default: {
24642 Assert(false, ExcInvalidHMatrixType(type));
24643 break;
24644 }
24645 }
24646}
24647
24648
24649template <int spacedim, typename Number>
24650void
24652 Vector<Number> &y,
24653 const Vector<Number> &x,
24654 const HMatrix<spacedim, Number> &starting_hmat,
24655 const HMatrixSupport::Property top_hmat_property) const
24656{
24657 Tvmult(y, real_type(1.0), x, starting_hmat, top_hmat_property);
24658}
24659
24660
24661template <int spacedim, typename Number>
24662template <typename Number2>
24663void
24665 Vector<Number> &y,
24666 const Number2 alpha,
24667 const Vector<Number> &x,
24668 const HMatrix<spacedim, Number> &starting_hmat,
24669 const HMatrixSupport::Property top_hmat_property) const
24670{
24671 static_assert(is_number_larger_or_equal<Number, Number2>());
24672 switch (type)
24673 {
24679 for (HMatrix *submatrix : submatrices)
24680 {
24681 submatrix->Tvmult(y, alpha, x, starting_hmat, top_hmat_property);
24682 }
24683
24684 break;
24685 }
24686 case FullMatrixType: {
24691 switch (top_hmat_property)
24692 {
24693 case HMatrixSupport::Property::general: {
24698 Assert(property == HMatrixSupport::Property::general,
24699 ExcInvalidHMatrixProperty(property));
24700 Assert(fullmatrix->get_property() ==
24701 LAPACKSupport::Property::general,
24702 ExcInvalidLAPACKFullMatrixProperty(
24703 fullmatrix->get_property()));
24704
24705 Vector<Number> local_y(n);
24706 Vector<Number> local_x(m);
24707
24711 for (size_type j = 0; j < m; j++)
24712 {
24713 local_x(j) = x((*row_index_range)[0] -
24714 (*starting_hmat.row_index_range)[0] + j);
24715 }
24716
24717 fullmatrix->Tvmult(local_y, local_x);
24718
24722 for (size_type i = 0; i < n; i++)
24723 {
24724 y((*col_index_range)[0] -
24725 (*starting_hmat.col_index_range)[0] + i) +=
24726 alpha * local_y(i);
24727 }
24728
24729 break;
24730 }
24731 case HMatrixSupport::Property::symmetric: {
24736 switch (block_type)
24737 {
24738 case HMatrixSupport::BlockType::diagonal_block: {
24744 Assert(property ==
24745 HMatrixSupport::Property::symmetric,
24746 ExcInvalidHMatrixProperty(property));
24751 Assert(fullmatrix->get_property() ==
24752 LAPACKSupport::Property::symmetric,
24753 ExcInvalidLAPACKFullMatrixProperty(
24754 fullmatrix->get_property()));
24755
24763 Vector<Number> local_y(n);
24764 Vector<Number> local_x(m);
24765
24769 for (size_type j = 0; j < m; j++)
24770 {
24771 local_x(j) =
24772 x((*row_index_range)[0] -
24773 (*starting_hmat.row_index_range)[0] + j);
24774 }
24775
24776 fullmatrix->Tvmult(local_y, local_x);
24777
24781 for (size_type i = 0; i < n; i++)
24782 {
24783 y((*col_index_range)[0] -
24784 (*starting_hmat.col_index_range)[0] + i) +=
24785 alpha * local_y(i);
24786 }
24787
24788 break;
24789 }
24790 case HMatrixSupport::BlockType::
24791 lower_triangular_block: {
24804 Assert(property == HMatrixSupport::Property::general,
24805 ExcInvalidHMatrixProperty(property));
24806 Assert(fullmatrix->get_property() ==
24807 LAPACKSupport::Property::general,
24808 ExcInvalidLAPACKFullMatrixProperty(
24809 fullmatrix->get_property()));
24810
24811 Vector<Number> local_y(n);
24812 Vector<Number> local_x(m);
24813
24817 for (size_type j = 0; j < m; j++)
24818 {
24819 local_x(j) =
24820 x((*row_index_range)[0] -
24821 (*starting_hmat.row_index_range)[0] + j);
24822 }
24823
24824 fullmatrix->Tvmult(local_y, local_x);
24825
24829 for (size_type i = 0; i < n; i++)
24830 {
24831 y((*col_index_range)[0] -
24832 (*starting_hmat.col_index_range)[0] + i) +=
24833 alpha * local_y(i);
24834 }
24835
24836 Vector<Number> local_y_for_vmult(m);
24837 Vector<Number> local_x_for_vmult(n);
24838
24842 for (size_type j = 0; j < n; j++)
24843 {
24844 local_x_for_vmult(j) =
24845 x((*col_index_range)[0] -
24846 (*starting_hmat.col_index_range)[0] + j);
24847 }
24848
24849 fullmatrix->vmult(local_y_for_vmult,
24850 local_x_for_vmult);
24851
24855 for (size_type i = 0; i < m; i++)
24856 {
24857 y((*row_index_range)[0] -
24858 (*starting_hmat.row_index_range)[0] + i) +=
24859 alpha * local_y_for_vmult(i);
24860 }
24861
24862 break;
24863 }
24864 case HMatrixSupport::BlockType::
24865 upper_triangular_block: {
24873 break;
24874 }
24875 default: {
24876 throw(ExcInvalidHMatrixBlockType(block_type));
24877
24878 break;
24879 }
24880 }
24881
24882 break;
24883 }
24884 case HMatrixSupport::Property::hermite_symmetric: {
24890 switch (block_type)
24891 {
24892 case HMatrixSupport::BlockType::diagonal_block: {
24898 Assert(property ==
24899 HMatrixSupport::Property::hermite_symmetric,
24900 ExcInvalidHMatrixProperty(property));
24905 Assert(fullmatrix->get_property() ==
24906 LAPACKSupport::Property::hermite_symmetric,
24907 ExcInvalidLAPACKFullMatrixProperty(
24908 fullmatrix->get_property()));
24909
24917 Vector<Number> local_y(n);
24918 Vector<Number> local_x(m);
24919
24923 for (size_type j = 0; j < m; j++)
24924 {
24925 local_x(j) =
24926 x((*row_index_range)[0] -
24927 (*starting_hmat.row_index_range)[0] + j);
24928 }
24929
24930 fullmatrix->Tvmult(local_y, local_x);
24931
24935 for (size_type i = 0; i < n; i++)
24936 {
24937 y((*col_index_range)[0] -
24938 (*starting_hmat.col_index_range)[0] + i) +=
24939 alpha * local_y(i);
24940 }
24941
24942 break;
24943 }
24944 case HMatrixSupport::BlockType::
24945 lower_triangular_block: {
24958 Assert(property == HMatrixSupport::Property::general,
24959 ExcInvalidHMatrixProperty(property));
24960 Assert(fullmatrix->get_property() ==
24961 LAPACKSupport::Property::general,
24962 ExcInvalidLAPACKFullMatrixProperty(
24963 fullmatrix->get_property()));
24964
24965 Vector<Number> local_y(n);
24966 Vector<Number> local_x(m);
24967
24971 for (size_type j = 0; j < m; j++)
24972 {
24973 local_x(j) =
24974 x((*row_index_range)[0] -
24975 (*starting_hmat.row_index_range)[0] + j);
24976 }
24977
24978 fullmatrix->Tvmult(local_y, local_x);
24979
24983 for (size_type i = 0; i < n; i++)
24984 {
24985 y((*col_index_range)[0] -
24986 (*starting_hmat.col_index_range)[0] + i) +=
24987 alpha * local_y(i);
24988 }
24989
24990 Vector<Number> local_y_for_vmult(m);
24991 Vector<Number> local_x_for_vmult(n);
24992
24996 for (size_type j = 0; j < n; j++)
24997 {
24998 local_x_for_vmult(j) =
24999 x((*col_index_range)[0] -
25000 (*starting_hmat.col_index_range)[0] + j);
25001 }
25002
25003 fullmatrix->Cvmult(local_y_for_vmult,
25004 local_x_for_vmult);
25005
25009 for (size_type i = 0; i < m; i++)
25010 {
25011 y((*row_index_range)[0] -
25012 (*starting_hmat.row_index_range)[0] + i) +=
25013 alpha * local_y_for_vmult(i);
25014 }
25015
25016 break;
25017 }
25018 case HMatrixSupport::BlockType::
25019 upper_triangular_block: {
25027 break;
25028 }
25029 default: {
25030 throw(ExcInvalidHMatrixBlockType(block_type));
25031
25032 break;
25033 }
25034 }
25035
25036 break;
25037 }
25038 case HMatrixSupport::Property::lower_triangular: {
25044 switch (block_type)
25045 {
25046 case HMatrixSupport::BlockType::diagonal_block: {
25052 Assert(property ==
25053 HMatrixSupport::Property::lower_triangular,
25054 ExcInvalidHMatrixProperty(property));
25059 Assert(fullmatrix->get_property() ==
25060 LAPACKSupport::Property::lower_triangular,
25061 ExcInvalidLAPACKFullMatrixProperty(
25062 fullmatrix->get_property()));
25063
25068 Vector<Number> local_y(n);
25069 Vector<Number> local_x(m);
25070
25074 for (size_type j = 0; j < m; j++)
25075 {
25076 local_x(j) =
25077 x((*row_index_range)[0] -
25078 (*starting_hmat.row_index_range)[0] + j);
25079 }
25080
25081 fullmatrix->Tvmult(local_y, local_x);
25082
25086 for (size_type i = 0; i < n; i++)
25087 {
25088 y((*col_index_range)[0] -
25089 (*starting_hmat.col_index_range)[0] + i) +=
25090 alpha * local_y(i);
25091 }
25092
25093 break;
25094 }
25095 case HMatrixSupport::BlockType::
25096 lower_triangular_block: {
25102 Assert(property == HMatrixSupport::Property::general,
25103 ExcInvalidHMatrixProperty(property));
25104 Assert(fullmatrix->get_property() ==
25105 LAPACKSupport::Property::general,
25106 ExcInvalidLAPACKFullMatrixProperty(
25107 fullmatrix->get_property()));
25108
25109 Vector<Number> local_y(n);
25110 Vector<Number> local_x(m);
25111
25115 for (size_type j = 0; j < m; j++)
25116 {
25117 local_x(j) =
25118 x((*row_index_range)[0] -
25119 (*starting_hmat.row_index_range)[0] + j);
25120 }
25121
25122 fullmatrix->Tvmult(local_y, local_x);
25123
25127 for (size_type i = 0; i < n; i++)
25128 {
25129 y((*col_index_range)[0] -
25130 (*starting_hmat.col_index_range)[0] + i) +=
25131 alpha * local_y(i);
25132 }
25133
25134 break;
25135 }
25136 case HMatrixSupport::BlockType::
25137 upper_triangular_block: {
25144 break;
25145 }
25146 default: {
25147 throw(ExcInvalidHMatrixBlockType(block_type));
25148
25149 break;
25150 }
25151 }
25152
25153 break;
25154 }
25155 case HMatrixSupport::Property::upper_triangular: {
25161 switch (block_type)
25162 {
25163 case HMatrixSupport::BlockType::diagonal_block: {
25169 Assert(property ==
25170 HMatrixSupport::Property::upper_triangular,
25171 ExcInvalidHMatrixProperty(property));
25176 Assert(fullmatrix->get_property() ==
25177 LAPACKSupport::Property::upper_triangular,
25178 ExcInvalidLAPACKFullMatrixProperty(
25179 fullmatrix->get_property()));
25180
25185 Vector<Number> local_y(n);
25186 Vector<Number> local_x(m);
25187
25191 for (size_type j = 0; j < m; j++)
25192 {
25193 local_x(j) =
25194 x((*row_index_range)[0] -
25195 (*starting_hmat.row_index_range)[0] + j);
25196 }
25197
25198 fullmatrix->Tvmult(local_y, local_x);
25199
25203 for (size_type i = 0; i < n; i++)
25204 {
25205 y((*col_index_range)[0] -
25206 (*starting_hmat.col_index_range)[0] + i) +=
25207 alpha * local_y(i);
25208 }
25209
25210 break;
25211 }
25212 case HMatrixSupport::BlockType::
25213 upper_triangular_block: {
25219 Assert(property == HMatrixSupport::Property::general,
25220 ExcInvalidHMatrixProperty(property));
25221 Assert(fullmatrix->get_property() ==
25222 LAPACKSupport::Property::general,
25223 ExcInvalidLAPACKFullMatrixProperty(
25224 fullmatrix->get_property()));
25225
25226 Vector<Number> local_y(n);
25227 Vector<Number> local_x(m);
25228
25232 for (size_type j = 0; j < m; j++)
25233 {
25234 local_x(j) =
25235 x((*row_index_range)[0] -
25236 (*starting_hmat.row_index_range)[0] + j);
25237 }
25238
25239 fullmatrix->Tvmult(local_y, local_x);
25240
25244 for (size_type i = 0; i < n; i++)
25245 {
25246 y((*col_index_range)[0] -
25247 (*starting_hmat.col_index_range)[0] + i) +=
25248 alpha * local_y(i);
25249 }
25250
25251 break;
25252 }
25253 case HMatrixSupport::BlockType::
25254 lower_triangular_block: {
25259 break;
25260 }
25261 default: {
25262 throw(ExcInvalidHMatrixBlockType(block_type));
25263
25264 break;
25265 }
25266 }
25267
25268 break;
25269 }
25270 default: {
25271 throw(ExcInvalidHMatrixProperty(top_hmat_property));
25272
25273 break;
25274 }
25275 }
25276
25277 break;
25278 }
25279 case RkMatrixType: {
25284 switch (top_hmat_property)
25285 {
25286 case HMatrixSupport::Property::general: {
25291 Assert(property == HMatrixSupport::Property::general,
25292 ExcInvalidHMatrixProperty(property));
25293
25294 Vector<Number> local_y(n);
25295 Vector<Number> local_x(m);
25296
25300 for (size_type j = 0; j < m; j++)
25301 {
25302 local_x(j) = x((*row_index_range)[0] -
25303 (*starting_hmat.row_index_range)[0] + j);
25304 }
25305
25306 rkmatrix->Tvmult(local_y, local_x);
25307
25311 for (size_type i = 0; i < n; i++)
25312 {
25313 y((*col_index_range)[0] -
25314 (*starting_hmat.col_index_range)[0] + i) +=
25315 alpha * local_y(i);
25316 }
25317
25318 break;
25319 }
25320 case HMatrixSupport::Property::symmetric: {
25325 switch (block_type)
25326 {
25327 case HMatrixSupport::BlockType::diagonal_block: {
25332 throw(ExcInvalidHMatrixBlockType(block_type));
25333
25334 break;
25335 }
25336 case HMatrixSupport::BlockType::
25337 lower_triangular_block: {
25350 Assert(property == HMatrixSupport::Property::general,
25351 ExcInvalidHMatrixProperty(property));
25352
25353 Vector<Number> local_y(n);
25354 Vector<Number> local_x(m);
25355
25359 for (size_type j = 0; j < m; j++)
25360 {
25361 local_x(j) =
25362 x((*row_index_range)[0] -
25363 (*starting_hmat.row_index_range)[0] + j);
25364 }
25365
25366 rkmatrix->Tvmult(local_y, local_x);
25367
25371 for (size_type i = 0; i < n; i++)
25372 {
25373 y((*col_index_range)[0] -
25374 (*starting_hmat.col_index_range)[0] + i) +=
25375 alpha * local_y(i);
25376 }
25377
25378 Vector<Number> local_y_for_vmult(m);
25379 Vector<Number> local_x_for_vmult(n);
25380
25384 for (size_type j = 0; j < n; j++)
25385 {
25386 local_x_for_vmult(j) =
25387 x((*col_index_range)[0] -
25388 (*starting_hmat.col_index_range)[0] + j);
25389 }
25390
25391 rkmatrix->vmult(local_y_for_vmult, local_x_for_vmult);
25392
25396 for (size_type i = 0; i < m; i++)
25397 {
25398 y((*row_index_range)[0] -
25399 (*starting_hmat.row_index_range)[0] + i) +=
25400 alpha * local_y_for_vmult(i);
25401 }
25402
25403 break;
25404 }
25405 case HMatrixSupport::BlockType::
25406 upper_triangular_block: {
25411 break;
25412 }
25413 default: {
25414 throw(ExcInvalidHMatrixBlockType(block_type));
25415
25416 break;
25417 }
25418 }
25419
25420 break;
25421 }
25422 case HMatrixSupport::Property::hermite_symmetric: {
25428 switch (block_type)
25429 {
25430 case HMatrixSupport::BlockType::diagonal_block: {
25435 throw(ExcInvalidHMatrixBlockType(block_type));
25436
25437 break;
25438 }
25439 case HMatrixSupport::BlockType::
25440 lower_triangular_block: {
25453 Assert(property == HMatrixSupport::Property::general,
25454 ExcInvalidHMatrixProperty(property));
25455
25456 Vector<Number> local_y(n);
25457 Vector<Number> local_x(m);
25458
25462 for (size_type j = 0; j < m; j++)
25463 {
25464 local_x(j) =
25465 x((*row_index_range)[0] -
25466 (*starting_hmat.row_index_range)[0] + j);
25467 }
25468
25469 rkmatrix->Tvmult(local_y, local_x);
25470
25474 for (size_type i = 0; i < n; i++)
25475 {
25476 y((*col_index_range)[0] -
25477 (*starting_hmat.col_index_range)[0] + i) +=
25478 alpha * local_y(i);
25479 }
25480
25481 Vector<Number> local_y_for_vmult(m);
25482 Vector<Number> local_x_for_vmult(n);
25483
25487 for (size_type j = 0; j < n; j++)
25488 {
25489 local_x_for_vmult(j) =
25490 x((*col_index_range)[0] -
25491 (*starting_hmat.col_index_range)[0] + j);
25492 }
25493
25494 rkmatrix->Cvmult(local_y_for_vmult,
25495 local_x_for_vmult);
25496
25500 for (size_type i = 0; i < m; i++)
25501 {
25502 y((*row_index_range)[0] -
25503 (*starting_hmat.row_index_range)[0] + i) +=
25504 alpha * local_y_for_vmult(i);
25505 }
25506
25507 break;
25508 }
25509 case HMatrixSupport::BlockType::
25510 upper_triangular_block: {
25515 break;
25516 }
25517 default: {
25518 throw(ExcInvalidHMatrixBlockType(block_type));
25519
25520 break;
25521 }
25522 }
25523
25524 break;
25525 }
25526 case HMatrixSupport::Property::lower_triangular: {
25532 switch (block_type)
25533 {
25534 case HMatrixSupport::BlockType::diagonal_block: {
25539 throw(ExcInvalidHMatrixBlockType(block_type));
25540
25541 break;
25542 }
25543 case HMatrixSupport::BlockType::
25544 lower_triangular_block: {
25550 Assert(property == HMatrixSupport::Property::general,
25551 ExcInvalidHMatrixProperty(property));
25552
25553 Vector<Number> local_y(n);
25554 Vector<Number> local_x(m);
25555
25559 for (size_type j = 0; j < m; j++)
25560 {
25561 local_x(j) =
25562 x((*row_index_range)[0] -
25563 (*starting_hmat.row_index_range)[0] + j);
25564 }
25565
25566 rkmatrix->Tvmult(local_y, local_x);
25567
25571 for (size_type i = 0; i < n; i++)
25572 {
25573 y((*col_index_range)[0] -
25574 (*starting_hmat.col_index_range)[0] + i) +=
25575 alpha * local_y(i);
25576 }
25577
25578 break;
25579 }
25580 case HMatrixSupport::BlockType::
25581 upper_triangular_block: {
25586 break;
25587 }
25588 default: {
25589 throw(ExcInvalidHMatrixBlockType(block_type));
25590
25591 break;
25592 }
25593 }
25594
25595 break;
25596 }
25597 case HMatrixSupport::Property::upper_triangular: {
25603 switch (block_type)
25604 {
25605 case HMatrixSupport::BlockType::diagonal_block: {
25610 throw(ExcInvalidHMatrixBlockType(block_type));
25611
25612 break;
25613 }
25614 case HMatrixSupport::BlockType::
25615 upper_triangular_block: {
25621 Assert(property == HMatrixSupport::Property::general,
25622 ExcInvalidHMatrixProperty(property));
25623
25624 Vector<Number> local_y(n);
25625 Vector<Number> local_x(m);
25626
25630 for (size_type j = 0; j < m; j++)
25631 {
25632 local_x(j) =
25633 x((*row_index_range)[0] -
25634 (*starting_hmat.row_index_range)[0] + j);
25635 }
25636
25637 rkmatrix->Tvmult(local_y, local_x);
25638
25642 for (size_type i = 0; i < n; i++)
25643 {
25644 y((*col_index_range)[0] -
25645 (*starting_hmat.col_index_range)[0] + i) +=
25646 alpha * local_y(i);
25647 }
25648
25649 break;
25650 }
25651 case HMatrixSupport::BlockType::
25652 lower_triangular_block: {
25657 break;
25658 }
25659 default: {
25660 throw(ExcInvalidHMatrixBlockType(block_type));
25661
25662 break;
25663 }
25664 }
25665
25666 break;
25667 }
25668 default: {
25669 throw(ExcInvalidHMatrixProperty(top_hmat_property));
25670
25671 break;
25672 }
25673 }
25674
25675 break;
25676 }
25678 default: {
25679 Assert(false, ExcInvalidHMatrixType(type));
25680 break;
25681 }
25682 }
25683}
25684
25685
25686template <int spacedim, typename Number>
25687template <typename Number2, typename Number3>
25688void
25690 const Number2 beta,
25691 Vector<Number> &y,
25692 const Number3 alpha,
25693 const Vector<Number> &x) const
25694{
25695 static_assert(is_number_larger_or_equal<Number, Number2>());
25696 static_assert(is_number_larger_or_equal<Number, Number3>());
25700 Assert(parent == nullptr, ExcInternalError());
25701
25702 if (property == HMatrixSupport::Property::symmetric)
25703 {
25704 vmult_serial_iterative(beta, y, alpha, x);
25705 }
25706 else
25707 {
25711 y *= beta;
25712
25716 for (size_type l = 0; l < leaf_set.size(); l++)
25717 {
25718 const size_type m = this->leaf_set[l]->m;
25719 const size_type n = this->leaf_set[l]->n;
25720
25721 Vector<Number> local_y_for_Tvmult(n);
25722 Vector<Number> local_x_for_Tvmult(m);
25723
25728 for (size_type i = 0; i < m; i++)
25729 {
25730 local_x_for_Tvmult(i) =
25731 x((*this->leaf_set[l]->row_index_range)[0] + i);
25732 }
25733
25734 switch (this->leaf_set[l]->type)
25735 {
25737 this->leaf_set[l]->fullmatrix->Tvmult(local_y_for_Tvmult,
25738 local_x_for_Tvmult);
25739
25740 break;
25741 }
25743 this->leaf_set[l]->rkmatrix->Tvmult(local_y_for_Tvmult,
25744 local_x_for_Tvmult);
25745
25746 break;
25747 }
25748 default: {
25749 Assert(false, ExcInvalidHMatrixType(this->leaf_set[l]->type));
25750
25751 break;
25752 }
25753 }
25754
25759 for (size_type j = 0; j < n; j++)
25760 {
25761 y((*this->leaf_set[l]->col_index_range)[0] + j) +=
25762 alpha * local_y_for_Tvmult(j);
25763 }
25764
25765 if (this->property == HMatrixSupport::Property::hermite_symmetric &&
25766 this->leaf_set[l]->block_type ==
25767 HMatrixSupport::BlockType::lower_triangular_block)
25768 {
25773 Vector<Number> local_y(m);
25774 Vector<Number> local_x(n);
25775
25779 for (size_type j = 0; j < n; j++)
25780 {
25781 local_x(j) = x((*this->leaf_set[l]->col_index_range)[0] + j);
25782 }
25783
25784 switch (this->leaf_set[l]->type)
25785 {
25787 this->leaf_set[l]->fullmatrix->Cvmult(local_y, local_x);
25788
25789 break;
25790 }
25792 this->leaf_set[l]->rkmatrix->Cvmult(local_y, local_x);
25793
25794 break;
25795 }
25796 default: {
25797 Assert(false,
25798 ExcInvalidHMatrixType(this->leaf_set[l]->type));
25799
25800 break;
25801 }
25802 }
25803
25807 for (size_type i = 0; i < m; i++)
25808 {
25809 y((*this->leaf_set[l]->row_index_range)[0] + i) +=
25810 alpha * local_y(i);
25811 }
25812 }
25813 }
25814 }
25815}
25816
25817
25818template <int spacedim, typename Number>
25819template <typename Number2, typename Number3>
25820void
25822 Vector<Number> &y,
25823 const Number3 alpha,
25824 const Vector<Number> &x) const
25825{
25826 static_assert(is_number_larger_or_equal<Number, Number2>());
25827 static_assert(is_number_larger_or_equal<Number, Number3>());
25831 Assert(parent == nullptr, ExcInternalError());
25832
25833 if (property == HMatrixSupport::Property::symmetric)
25834 {
25835 vmult_task_parallel(beta, y, alpha, x);
25836 }
25837 else
25838 {
25839 const unsigned int thread_num = data_for_vmult_or_tvmult_threads->size();
25840
25845 if (thread_num > 1)
25846 {
25847 // Set OpenBLAS num threads to 1 when task parallelization is used.
25848 const int blas_num_threads = openblas_get_num_threads();
25849 openblas_set_num_threads(1);
25850
25856 auto local_scale_and_multiplication =
25857 [this, beta, alpha, &y, &x](const unsigned int thread_no) -> void {
25861 for (size_type i =
25862 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25863 .tvmult_result_index_range[0];
25864 i < (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25865 .tvmult_result_index_range[1];
25866 i++)
25867 {
25868 y[i] *= beta;
25869 }
25870
25874 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25875 .local_tvmult_result = Number(0.);
25876 if (this->property == HMatrixSupport::Property::hermite_symmetric)
25877 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25878 .local_vmult_result = Number(0.);
25879
25884 for (unsigned int l =
25885 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25886 .leaf_set_interval.first;
25887 l <= (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25888 .leaf_set_interval.second;
25889 l++)
25890 {
25891 const size_type m = this->leaf_set[l]->m;
25892 const size_type n = this->leaf_set[l]->n;
25893
25894 Vector<Number> local_y_for_Tvmult(n);
25895 Vector<Number> local_x_for_Tvmult(m);
25896
25900 for (size_type i = 0; i < m; i++)
25901 {
25902 local_x_for_Tvmult(i) =
25903 x((*this->leaf_set[l]->row_index_range)[0] + i);
25904 }
25905
25906 switch (this->leaf_set[l]->type)
25907 {
25909 this->leaf_set[l]->fullmatrix->Tvmult(
25910 local_y_for_Tvmult, local_x_for_Tvmult);
25911
25912 break;
25913 }
25915 this->leaf_set[l]->rkmatrix->Tvmult(local_y_for_Tvmult,
25916 local_x_for_Tvmult);
25917
25918 break;
25919 }
25920 default: {
25921 Assert(false,
25922 ExcInvalidHMatrixType(this->leaf_set[l]->type));
25923
25924 break;
25925 }
25926 }
25927
25933 for (size_type j = 0; j < n; j++)
25934 {
25935 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25936 .local_tvmult_result(
25937 (*this->leaf_set[l]->col_index_range)[0] -
25938 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25939 .local_tvmult_result_index_range[0] +
25940 j) += alpha * local_y_for_Tvmult(j);
25941 }
25942
25943 if (this->property ==
25944 HMatrixSupport::Property::hermite_symmetric &&
25945 this->leaf_set[l]->block_type ==
25946 HMatrixSupport::BlockType::lower_triangular_block)
25947 {
25952 Vector<Number> local_y(m);
25953 Vector<Number> local_x(n);
25954
25958 for (size_type j = 0; j < n; j++)
25959 {
25960 local_x(j) =
25961 x((*this->leaf_set[l]->col_index_range)[0] + j);
25962 }
25963
25964 switch (this->leaf_set[l]->type)
25965 {
25967 this->leaf_set[l]->fullmatrix->Cvmult(local_y,
25968 local_x);
25969
25970 break;
25971 }
25973 this->leaf_set[l]->rkmatrix->Cvmult(local_y,
25974 local_x);
25975
25976 break;
25977 }
25978 default: {
25979 Assert(false,
25980 ExcInvalidHMatrixType(
25981 this->leaf_set[l]->type));
25982
25983 break;
25984 }
25985 }
25986
25992 for (size_type i = 0; i < m; i++)
25993 {
25994 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25995 .local_vmult_result(
25996 (*this->leaf_set[l]->row_index_range)[0] -
25997 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
25998 .local_vmult_result_index_range[0] +
25999 i) += alpha * local_y(i);
26000 }
26001 }
26002 }
26003 };
26004
26005 Threads::TaskGroup<void> local_scaling_and_multiplication_tasks;
26006 for (unsigned int i = 0; i < thread_num; i++)
26007 {
26008 local_scaling_and_multiplication_tasks +=
26009 Threads::new_task(std::bind(local_scale_and_multiplication, i));
26010 }
26011
26012 local_scaling_and_multiplication_tasks.join_all();
26013
26014 auto assemble_contribution_from_all_threads =
26015 [this, &y](const unsigned int thread_no) -> void {
26016 unsigned int other_thread_no = 0;
26017 for (const auto &range_intersection :
26018 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
26019 .tvmult_result_index_ranges_contributed_from_other_threads)
26020 {
26021 for (size_type i = range_intersection[0];
26022 i < range_intersection[1];
26023 i++)
26024 {
26025 y(i) +=
26026 (*this->data_for_vmult_or_tvmult_threads)[other_thread_no]
26027 .local_tvmult_result(
26028 i - (*this->data_for_vmult_or_tvmult_threads)
26029 [other_thread_no]
26030 .local_tvmult_result_index_range[0]);
26031 }
26032
26033 other_thread_no++;
26034 }
26035
26036 if (this->property == HMatrixSupport::Property::hermite_symmetric)
26037 {
26038 unsigned int other_thread_no = 0;
26039 for (
26040 const auto &range_intersection :
26041 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
26042 .vmult_result_index_ranges_contributed_from_other_threads)
26043 {
26044 for (size_type i = range_intersection[0];
26045 i < range_intersection[1];
26046 i++)
26047 {
26048 y(i) +=
26049 (*this->data_for_vmult_or_tvmult_threads)
26050 [other_thread_no]
26051 .local_vmult_result(
26052 i - (*this->data_for_vmult_or_tvmult_threads)
26053 [other_thread_no]
26054 .local_vmult_result_index_range[0]);
26055 }
26056
26057 other_thread_no++;
26058 }
26059 }
26060 };
26061
26062 Threads::TaskGroup<void> assembly_tasks;
26063 for (unsigned int i = 0; i < thread_num; i++)
26064 {
26065 assembly_tasks += Threads::new_task(
26066 std::bind(assemble_contribution_from_all_threads, i));
26067 }
26068
26069 assembly_tasks.join_all();
26070
26071 // Restore the original OpenBLAS num threads.
26072 openblas_set_num_threads(blas_num_threads);
26073 }
26074 else
26075 {
26076 Tvmult_serial_iterative(beta, y, alpha, x);
26077 }
26078 }
26079}
26080
26081
26082template <int spacedim, typename Number>
26083void
26085 const Vector<Number> &x) const
26086{
26087 if (!vmult_strategy)
26088 {
26089 Assert(false, ExcInternalError());
26090 }
26091 else
26092 vmult_strategy->Tvmult(y, *this, x);
26093}
26094
26095
26096template <int spacedim, typename Number>
26097void
26099 const Vector<Number> &x) const
26100{
26101 if (!vmult_strategy)
26102 {
26103 Assert(false, ExcInternalError());
26104 }
26105 else
26106 vmult_strategy->Tvmult_add(y, *this, x);
26107}
26108
26109
26110template <int spacedim, typename Number>
26111template <typename Number2>
26112void
26114 const Number2 alpha,
26115 const Vector<Number> &x) const
26116{
26117 if (!vmult_strategy)
26118 {
26119 Assert(false, ExcInternalError());
26120 }
26121 else
26122 vmult_strategy->Tvmult(y, alpha, *this, x);
26123}
26124
26125
26126template <int spacedim, typename Number>
26127template <typename Number2>
26128void
26130 const Number2 alpha,
26131 const Vector<Number> &x) const
26132{
26133 if (!vmult_strategy)
26134 {
26135 Assert(false, ExcInternalError());
26136 }
26137 else
26138 vmult_strategy->Tvmult_add(y, alpha, *this, x);
26139}
26140
26141
26142template <int spacedim, typename Number>
26143void
26145 Vector<Number> &y,
26146 const Vector<Number> &x,
26147 const HMatrixSupport::Property top_hmat_property) const
26148{
26149 Hvmult(y, real_type(1.0), x, top_hmat_property);
26150}
26151
26152
26153template <int spacedim, typename Number>
26154template <typename Number2>
26155void
26157 Vector<Number> &y,
26158 const Number2 alpha,
26159 const Vector<Number> &x,
26160 const HMatrixSupport::Property top_hmat_property) const
26161{
26162 static_assert(is_number_larger_or_equal<Number, Number2>());
26163 if constexpr (numbers::NumberTraits<Number>::is_complex)
26164 {
26165 switch (type)
26166 {
26172 for (HMatrix *submatrix : submatrices)
26173 {
26174 submatrix->Hvmult(y, alpha, x, top_hmat_property);
26175 }
26176
26177 break;
26178 }
26179 case FullMatrixType: {
26184 switch (top_hmat_property)
26185 {
26186 case HMatrixSupport::Property::general: {
26191 Assert(property == HMatrixSupport::Property::general,
26192 ExcInvalidHMatrixProperty(property));
26193 Assert(fullmatrix->get_property() ==
26194 LAPACKSupport::Property::general,
26195 ExcInvalidLAPACKFullMatrixProperty(
26196 fullmatrix->get_property()));
26197
26198 Vector<Number> local_y(n);
26199 Vector<Number> local_x(m);
26200
26204 for (size_type j = 0; j < m; j++)
26205 {
26206 local_x(j) = x((*row_index_range)[0] + j);
26207 }
26208
26209 fullmatrix->Hvmult(local_y, local_x);
26210
26214 for (size_type i = 0; i < n; i++)
26215 {
26216 y((*col_index_range)[0] + i) += alpha * local_y(i);
26217 }
26218
26219 break;
26220 }
26221 case HMatrixSupport::Property::symmetric: {
26227 switch (block_type)
26228 {
26229 case HMatrixSupport::BlockType::diagonal_block: {
26235 Assert(property ==
26236 HMatrixSupport::Property::symmetric,
26237 ExcInvalidHMatrixProperty(property));
26242 Assert(fullmatrix->get_property() ==
26243 LAPACKSupport::Property::symmetric,
26244 ExcInvalidLAPACKFullMatrixProperty(
26245 fullmatrix->get_property()));
26246
26255 Vector<Number> local_y(n);
26256 Vector<Number> local_x(m);
26257
26262 for (size_type j = 0; j < m; j++)
26263 {
26264 local_x(j) = x((*row_index_range)[0] + j);
26265 }
26266
26267 fullmatrix->Hvmult(local_y, local_x);
26268
26272 for (size_type i = 0; i < n; i++)
26273 {
26274 y((*col_index_range)[0] + i) +=
26275 alpha * local_y(i);
26276 }
26277
26278 break;
26279 }
26280 case HMatrixSupport::BlockType::
26281 lower_triangular_block: {
26295 Assert(property ==
26296 HMatrixSupport::Property::general,
26297 ExcInvalidHMatrixProperty(property));
26298 Assert(fullmatrix->get_property() ==
26299 LAPACKSupport::Property::general,
26300 ExcInvalidLAPACKFullMatrixProperty(
26301 fullmatrix->get_property()));
26302
26303 Vector<Number> local_y(n);
26304 Vector<Number> local_x(m);
26305
26310 for (size_type j = 0; j < m; j++)
26311 {
26312 local_x(j) = x((*row_index_range)[0] + j);
26313 }
26314
26315 fullmatrix->Hvmult(local_y, local_x);
26316
26320 for (size_type i = 0; i < n; i++)
26321 {
26322 y((*col_index_range)[0] + i) +=
26323 alpha * local_y(i);
26324 }
26325
26326 Vector<Number> local_y_for_vmult(m);
26327 Vector<Number> local_x_for_vmult(n);
26328
26332 for (size_type j = 0; j < n; j++)
26333 {
26334 local_x_for_vmult(j) =
26335 x((*col_index_range)[0] + j);
26336 }
26337
26338 fullmatrix->Cvmult(local_y_for_vmult,
26339 local_x_for_vmult);
26340
26344 for (size_type i = 0; i < m; i++)
26345 {
26346 y((*row_index_range)[0] + i) +=
26347 alpha * local_y_for_vmult(i);
26348 }
26349
26350 break;
26351 }
26352 case HMatrixSupport::BlockType::
26353 upper_triangular_block: {
26361 break;
26362 }
26363 default: {
26364 throw(ExcInvalidHMatrixBlockType(block_type));
26365
26366 break;
26367 }
26368 }
26369
26370 break;
26371 }
26372 case HMatrixSupport::Property::hermite_symmetric: {
26378 switch (block_type)
26379 {
26380 case HMatrixSupport::BlockType::diagonal_block: {
26386 Assert(
26387 property ==
26388 HMatrixSupport::Property::hermite_symmetric,
26389 ExcInvalidHMatrixProperty(property));
26394 Assert(
26395 fullmatrix->get_property() ==
26396 LAPACKSupport::Property::hermite_symmetric,
26397 ExcInvalidLAPACKFullMatrixProperty(
26398 fullmatrix->get_property()));
26399
26408 Vector<Number> local_y(n);
26409 Vector<Number> local_x(m);
26410
26415 for (size_type j = 0; j < m; j++)
26416 {
26417 local_x(j) = x((*row_index_range)[0] + j);
26418 }
26419
26420 fullmatrix->Hvmult(local_y, local_x);
26421
26425 for (size_type i = 0; i < n; i++)
26426 {
26427 y((*col_index_range)[0] + i) +=
26428 alpha * local_y(i);
26429 }
26430
26431 break;
26432 }
26433 case HMatrixSupport::BlockType::
26434 lower_triangular_block: {
26448 Assert(property ==
26449 HMatrixSupport::Property::general,
26450 ExcInvalidHMatrixProperty(property));
26451 Assert(fullmatrix->get_property() ==
26452 LAPACKSupport::Property::general,
26453 ExcInvalidLAPACKFullMatrixProperty(
26454 fullmatrix->get_property()));
26455
26456 Vector<Number> local_y(n);
26457 Vector<Number> local_x(m);
26458
26463 for (size_type j = 0; j < m; j++)
26464 {
26465 local_x(j) = x((*row_index_range)[0] + j);
26466 }
26467
26468 fullmatrix->Hvmult(local_y, local_x);
26469
26473 for (size_type i = 0; i < n; i++)
26474 {
26475 y((*col_index_range)[0] + i) +=
26476 alpha * local_y(i);
26477 }
26478
26479 Vector<Number> local_y_for_vmult(m);
26480 Vector<Number> local_x_for_vmult(n);
26481
26485 for (size_type j = 0; j < n; j++)
26486 {
26487 local_x_for_vmult(j) =
26488 x((*col_index_range)[0] + j);
26489 }
26490
26491 fullmatrix->vmult(local_y_for_vmult,
26492 local_x_for_vmult);
26493
26497 for (size_type i = 0; i < m; i++)
26498 {
26499 y((*row_index_range)[0] + i) +=
26500 alpha * local_y_for_vmult(i);
26501 }
26502
26503 break;
26504 }
26505 case HMatrixSupport::BlockType::
26506 upper_triangular_block: {
26514 break;
26515 }
26516 default: {
26517 throw(ExcInvalidHMatrixBlockType(block_type));
26518
26519 break;
26520 }
26521 }
26522
26523 break;
26524 }
26525 case HMatrixSupport::Property::lower_triangular: {
26531 switch (block_type)
26532 {
26533 case HMatrixSupport::BlockType::diagonal_block: {
26539 Assert(
26540 property ==
26541 HMatrixSupport::Property::lower_triangular,
26542 ExcInvalidHMatrixProperty(property));
26547 Assert(
26548 fullmatrix->get_property() ==
26549 LAPACKSupport::Property::lower_triangular,
26550 ExcInvalidLAPACKFullMatrixProperty(
26551 fullmatrix->get_property()));
26552
26557 Vector<Number> local_y(n);
26558 Vector<Number> local_x(m);
26559
26564 for (size_type j = 0; j < m; j++)
26565 {
26566 local_x(j) = x((*row_index_range)[0] + j);
26567 }
26568
26569 fullmatrix->Hvmult(local_y, local_x);
26570
26574 for (size_type i = 0; i < n; i++)
26575 {
26576 y((*col_index_range)[0] + i) +=
26577 alpha * local_y(i);
26578 }
26579
26580 break;
26581 }
26582 case HMatrixSupport::BlockType::
26583 lower_triangular_block: {
26589 Assert(property ==
26590 HMatrixSupport::Property::general,
26591 ExcInvalidHMatrixProperty(property));
26592 Assert(fullmatrix->get_property() ==
26593 LAPACKSupport::Property::general,
26594 ExcInvalidLAPACKFullMatrixProperty(
26595 fullmatrix->get_property()));
26596
26597 Vector<Number> local_y(n);
26598 Vector<Number> local_x(m);
26599
26604 for (size_type j = 0; j < m; j++)
26605 {
26606 local_x(j) = x((*row_index_range)[0] + j);
26607 }
26608
26609 fullmatrix->Hvmult(local_y, local_x);
26610
26614 for (size_type i = 0; i < n; i++)
26615 {
26616 y((*col_index_range)[0] + i) +=
26617 alpha * local_y(i);
26618 }
26619
26620 break;
26621 }
26622 case HMatrixSupport::BlockType::
26623 upper_triangular_block: {
26630 break;
26631 }
26632 default: {
26633 throw(ExcInvalidHMatrixBlockType(block_type));
26634
26635 break;
26636 }
26637 }
26638
26639 break;
26640 }
26641 case HMatrixSupport::Property::upper_triangular: {
26647 switch (block_type)
26648 {
26649 case HMatrixSupport::BlockType::diagonal_block: {
26655 Assert(
26656 property ==
26657 HMatrixSupport::Property::upper_triangular,
26658 ExcInvalidHMatrixProperty(property));
26663 Assert(
26664 fullmatrix->get_property() ==
26665 LAPACKSupport::Property::upper_triangular,
26666 ExcInvalidLAPACKFullMatrixProperty(
26667 fullmatrix->get_property()));
26668
26673 Vector<Number> local_y(n);
26674 Vector<Number> local_x(m);
26675
26680 for (size_type j = 0; j < m; j++)
26681 {
26682 local_x(j) = x((*row_index_range)[0] + j);
26683 }
26684
26685 fullmatrix->Hvmult(local_y, local_x);
26686
26690 for (size_type i = 0; i < n; i++)
26691 {
26692 y((*col_index_range)[0] + i) +=
26693 alpha * local_y(i);
26694 }
26695
26696 break;
26697 }
26698 case HMatrixSupport::BlockType::
26699 upper_triangular_block: {
26705 Assert(property ==
26706 HMatrixSupport::Property::general,
26707 ExcInvalidHMatrixProperty(property));
26708 Assert(fullmatrix->get_property() ==
26709 LAPACKSupport::Property::general,
26710 ExcInvalidLAPACKFullMatrixProperty(
26711 fullmatrix->get_property()));
26712
26713 Vector<Number> local_y(n);
26714 Vector<Number> local_x(m);
26715
26720 for (size_type j = 0; j < m; j++)
26721 {
26722 local_x(j) = x((*row_index_range)[0] + j);
26723 }
26724
26725 fullmatrix->Hvmult(local_y, local_x);
26726
26730 for (size_type i = 0; i < n; i++)
26731 {
26732 y((*col_index_range)[0] + i) +=
26733 alpha * local_y(i);
26734 }
26735
26736 break;
26737 }
26738 case HMatrixSupport::BlockType::
26739 lower_triangular_block: {
26744 break;
26745 }
26746 default: {
26747 throw(ExcInvalidHMatrixBlockType(block_type));
26748
26749 break;
26750 }
26751 }
26752
26753 break;
26754 }
26755 default: {
26756 throw(ExcInvalidHMatrixProperty(top_hmat_property));
26757
26758 break;
26759 }
26760 }
26761
26762 break;
26763 }
26764 case RkMatrixType: {
26769 switch (top_hmat_property)
26770 {
26771 case HMatrixSupport::Property::general: {
26776 Assert(property == HMatrixSupport::Property::general,
26777 ExcInvalidHMatrixProperty(property));
26778
26779 Vector<Number> local_y(n);
26780 Vector<Number> local_x(m);
26781
26785 for (size_type j = 0; j < m; j++)
26786 {
26787 local_x(j) = x((*row_index_range)[0] + j);
26788 }
26789
26790 rkmatrix->Hvmult(local_y, local_x);
26791
26795 for (size_type i = 0; i < n; i++)
26796 {
26797 y((*col_index_range)[0] + i) += alpha * local_y(i);
26798 }
26799
26800 break;
26801 }
26802 case HMatrixSupport::Property::symmetric: {
26808 switch (block_type)
26809 {
26810 case HMatrixSupport::BlockType::diagonal_block: {
26815 throw(ExcInvalidHMatrixBlockType(block_type));
26816
26817 break;
26818 }
26819 case HMatrixSupport::BlockType::
26820 lower_triangular_block: {
26834 Assert(property ==
26835 HMatrixSupport::Property::general,
26836 ExcInvalidHMatrixProperty(property));
26837
26838 Vector<Number> local_y(n);
26839 Vector<Number> local_x(m);
26840
26845 for (size_type j = 0; j < m; j++)
26846 {
26847 local_x(j) = x((*row_index_range)[0] + j);
26848 }
26849
26850 rkmatrix->Hvmult(local_y, local_x);
26851
26855 for (size_type i = 0; i < n; i++)
26856 {
26857 y((*col_index_range)[0] + i) +=
26858 alpha * local_y(i);
26859 }
26860
26861 Vector<Number> local_y_for_vmult(m);
26862 Vector<Number> local_x_for_vmult(n);
26863
26867 for (size_type j = 0; j < n; j++)
26868 {
26869 local_x_for_vmult(j) =
26870 x((*col_index_range)[0] + j);
26871 }
26872
26873 rkmatrix->Cvmult(local_y_for_vmult,
26874 local_x_for_vmult);
26875
26879 for (size_type i = 0; i < m; i++)
26880 {
26881 y((*row_index_range)[0] + i) +=
26882 alpha * local_y_for_vmult(i);
26883 }
26884
26885 break;
26886 }
26887 case HMatrixSupport::BlockType::
26888 upper_triangular_block: {
26893 break;
26894 }
26895 default: {
26896 throw(ExcInvalidHMatrixBlockType(block_type));
26897
26898 break;
26899 }
26900 }
26901
26902 break;
26903 }
26904 case HMatrixSupport::Property::hermite_symmetric: {
26910 switch (block_type)
26911 {
26912 case HMatrixSupport::BlockType::diagonal_block: {
26917 throw(ExcInvalidHMatrixBlockType(block_type));
26918
26919 break;
26920 }
26921 case HMatrixSupport::BlockType::
26922 lower_triangular_block: {
26936 Assert(property ==
26937 HMatrixSupport::Property::general,
26938 ExcInvalidHMatrixProperty(property));
26939
26940 Vector<Number> local_y(n);
26941 Vector<Number> local_x(m);
26942
26947 for (size_type j = 0; j < m; j++)
26948 {
26949 local_x(j) = x((*row_index_range)[0] + j);
26950 }
26951
26952 rkmatrix->Hvmult(local_y, local_x);
26953
26957 for (size_type i = 0; i < n; i++)
26958 {
26959 y((*col_index_range)[0] + i) +=
26960 alpha * local_y(i);
26961 }
26962
26963 Vector<Number> local_y_for_vmult(m);
26964 Vector<Number> local_x_for_vmult(n);
26965
26969 for (size_type j = 0; j < n; j++)
26970 {
26971 local_x_for_vmult(j) =
26972 x((*col_index_range)[0] + j);
26973 }
26974
26975 rkmatrix->vmult(local_y_for_vmult,
26976 local_x_for_vmult);
26977
26981 for (size_type i = 0; i < m; i++)
26982 {
26983 y((*row_index_range)[0] + i) +=
26984 alpha * local_y_for_vmult(i);
26985 }
26986
26987 break;
26988 }
26989 case HMatrixSupport::BlockType::
26990 upper_triangular_block: {
26995 break;
26996 }
26997 default: {
26998 throw(ExcInvalidHMatrixBlockType(block_type));
26999
27000 break;
27001 }
27002 }
27003
27004 break;
27005 }
27006 case HMatrixSupport::Property::lower_triangular: {
27012 switch (block_type)
27013 {
27014 case HMatrixSupport::BlockType::diagonal_block: {
27019 throw(ExcInvalidHMatrixBlockType(block_type));
27020
27021 break;
27022 }
27023 case HMatrixSupport::BlockType::
27024 lower_triangular_block: {
27030 Assert(property ==
27031 HMatrixSupport::Property::general,
27032 ExcInvalidHMatrixProperty(property));
27033
27034 Vector<Number> local_y(n);
27035 Vector<Number> local_x(m);
27036
27040 for (size_type j = 0; j < m; j++)
27041 {
27042 local_x(j) = x((*row_index_range)[0] + j);
27043 }
27044
27045 rkmatrix->Hvmult(local_y, local_x);
27046
27050 for (size_type i = 0; i < n; i++)
27051 {
27052 y((*col_index_range)[0] + i) +=
27053 alpha * local_y(i);
27054 }
27055
27056 break;
27057 }
27058 case HMatrixSupport::BlockType::
27059 upper_triangular_block: {
27064 break;
27065 }
27066 default: {
27067 throw(ExcInvalidHMatrixBlockType(block_type));
27068
27069 break;
27070 }
27071 }
27072
27073 break;
27074 }
27075 case HMatrixSupport::Property::upper_triangular: {
27081 switch (block_type)
27082 {
27083 case HMatrixSupport::BlockType::diagonal_block: {
27088 throw(ExcInvalidHMatrixBlockType(block_type));
27089
27090 break;
27091 }
27092 case HMatrixSupport::BlockType::
27093 upper_triangular_block: {
27099 Assert(property ==
27100 HMatrixSupport::Property::general,
27101 ExcInvalidHMatrixProperty(property));
27102
27103 Vector<Number> local_y(n);
27104 Vector<Number> local_x(m);
27105
27109 for (size_type j = 0; j < m; j++)
27110 {
27111 local_x(j) = x((*row_index_range)[0] + j);
27112 }
27113
27114 rkmatrix->Hvmult(local_y, local_x);
27115
27119 for (size_type i = 0; i < n; i++)
27120 {
27121 y((*col_index_range)[0] + i) +=
27122 alpha * local_y(i);
27123 }
27124
27125 break;
27126 }
27127 case HMatrixSupport::BlockType::
27128 lower_triangular_block: {
27133 break;
27134 }
27135 default: {
27136 throw(ExcInvalidHMatrixBlockType(block_type));
27137
27138 break;
27139 }
27140 }
27141
27142 break;
27143 }
27144 default: {
27145 throw(ExcInvalidHMatrixProperty(top_hmat_property));
27146
27147 break;
27148 }
27149 }
27150
27151 break;
27152 }
27154 default: {
27155 Assert(false, ExcInvalidHMatrixType(type));
27156 break;
27157 }
27158 }
27159 }
27160 else
27161 {
27162 this->Tvmult(y, alpha, x, top_hmat_property);
27163 }
27164}
27165
27166
27167template <int spacedim, typename Number>
27168void
27170 Vector<Number> &y,
27171 const Vector<Number> &x,
27172 const HMatrix<spacedim, Number> &starting_hmat,
27173 const HMatrixSupport::Property top_hmat_property) const
27174{
27175 Hvmult(y, real_type(1.0), x, starting_hmat, top_hmat_property);
27176}
27177
27178
27179template <int spacedim, typename Number>
27180template <typename Number2>
27181void
27183 Vector<Number> &y,
27184 const Number2 alpha,
27185 const Vector<Number> &x,
27186 const HMatrix<spacedim, Number> &starting_hmat,
27187 const HMatrixSupport::Property top_hmat_property) const
27188{
27189 static_assert(is_number_larger_or_equal<Number, Number2>());
27190 if constexpr (numbers::NumberTraits<Number>::is_complex)
27191 {
27192 switch (type)
27193 {
27199 for (HMatrix *submatrix : submatrices)
27200 {
27201 submatrix->Hvmult(
27202 y, alpha, x, starting_hmat, top_hmat_property);
27203 }
27204
27205 break;
27206 }
27207 case FullMatrixType: {
27212 switch (top_hmat_property)
27213 {
27214 case HMatrixSupport::Property::general: {
27219 Assert(property == HMatrixSupport::Property::general,
27220 ExcInvalidHMatrixProperty(property));
27221 Assert(fullmatrix->get_property() ==
27222 LAPACKSupport::Property::general,
27223 ExcInvalidLAPACKFullMatrixProperty(
27224 fullmatrix->get_property()));
27225
27226 Vector<Number> local_y(n);
27227 Vector<Number> local_x(m);
27228
27232 for (size_type j = 0; j < m; j++)
27233 {
27234 local_x(j) =
27235 x((*row_index_range)[0] -
27236 (*starting_hmat.row_index_range)[0] + j);
27237 }
27238
27239 fullmatrix->Hvmult(local_y, local_x);
27240
27244 for (size_type i = 0; i < n; i++)
27245 {
27246 y((*col_index_range)[0] -
27247 (*starting_hmat.col_index_range)[0] + i) +=
27248 alpha * local_y(i);
27249 }
27250
27251 break;
27252 }
27253 case HMatrixSupport::Property::symmetric: {
27259 switch (block_type)
27260 {
27261 case HMatrixSupport::BlockType::diagonal_block: {
27267 Assert(property ==
27268 HMatrixSupport::Property::symmetric,
27269 ExcInvalidHMatrixProperty(property));
27274 Assert(fullmatrix->get_property() ==
27275 LAPACKSupport::Property::symmetric,
27276 ExcInvalidLAPACKFullMatrixProperty(
27277 fullmatrix->get_property()));
27278
27287 Vector<Number> local_y(n);
27288 Vector<Number> local_x(m);
27289
27294 for (size_type j = 0; j < m; j++)
27295 {
27296 local_x(j) =
27297 x((*row_index_range)[0] -
27298 (*starting_hmat.row_index_range)[0] + j);
27299 }
27300
27301 fullmatrix->Hvmult(local_y, local_x);
27302
27306 for (size_type i = 0; i < n; i++)
27307 {
27308 y((*col_index_range)[0] -
27309 (*starting_hmat.col_index_range)[0] + i) +=
27310 alpha * local_y(i);
27311 }
27312
27313 break;
27314 }
27315 case HMatrixSupport::BlockType::
27316 lower_triangular_block: {
27330 Assert(property ==
27331 HMatrixSupport::Property::general,
27332 ExcInvalidHMatrixProperty(property));
27333 Assert(fullmatrix->get_property() ==
27334 LAPACKSupport::Property::general,
27335 ExcInvalidLAPACKFullMatrixProperty(
27336 fullmatrix->get_property()));
27337
27338 Vector<Number> local_y(n);
27339 Vector<Number> local_x(m);
27340
27345 for (size_type j = 0; j < m; j++)
27346 {
27347 local_x(j) =
27348 x((*row_index_range)[0] -
27349 (*starting_hmat.row_index_range)[0] + j);
27350 }
27351
27352 fullmatrix->Hvmult(local_y, local_x);
27353
27357 for (size_type i = 0; i < n; i++)
27358 {
27359 y((*col_index_range)[0] -
27360 (*starting_hmat.col_index_range)[0] + i) +=
27361 alpha * local_y(i);
27362 }
27363
27364 Vector<Number> local_y_for_vmult(m);
27365 Vector<Number> local_x_for_vmult(n);
27366
27370 for (size_type j = 0; j < n; j++)
27371 {
27372 local_x_for_vmult(j) =
27373 x((*col_index_range)[0] -
27374 (*starting_hmat.col_index_range)[0] + j);
27375 }
27376
27377 fullmatrix->Cvmult(local_y_for_vmult,
27378 local_x_for_vmult);
27379
27383 for (size_type i = 0; i < m; i++)
27384 {
27385 y((*row_index_range)[0] -
27386 (*starting_hmat.row_index_range)[0] + i) +=
27387 alpha * local_y_for_vmult(i);
27388 }
27389
27390 break;
27391 }
27392 case HMatrixSupport::BlockType::
27393 upper_triangular_block: {
27401 break;
27402 }
27403 default: {
27404 throw(ExcInvalidHMatrixBlockType(block_type));
27405
27406 break;
27407 }
27408 }
27409
27410 break;
27411 }
27412 case HMatrixSupport::Property::hermite_symmetric: {
27418 switch (block_type)
27419 {
27420 case HMatrixSupport::BlockType::diagonal_block: {
27426 Assert(
27427 property ==
27428 HMatrixSupport::Property::hermite_symmetric,
27429 ExcInvalidHMatrixProperty(property));
27434 Assert(
27435 fullmatrix->get_property() ==
27436 LAPACKSupport::Property::hermite_symmetric,
27437 ExcInvalidLAPACKFullMatrixProperty(
27438 fullmatrix->get_property()));
27439
27448 Vector<Number> local_y(n);
27449 Vector<Number> local_x(m);
27450
27455 for (size_type j = 0; j < m; j++)
27456 {
27457 local_x(j) =
27458 x((*row_index_range)[0] -
27459 (*starting_hmat.row_index_range)[0] + j);
27460 }
27461
27462 fullmatrix->Hvmult(local_y, local_x);
27463
27467 for (size_type i = 0; i < n; i++)
27468 {
27469 y((*col_index_range)[0] -
27470 (*starting_hmat.col_index_range)[0] + i) +=
27471 alpha * local_y(i);
27472 }
27473
27474 break;
27475 }
27476 case HMatrixSupport::BlockType::
27477 lower_triangular_block: {
27491 Assert(property ==
27492 HMatrixSupport::Property::general,
27493 ExcInvalidHMatrixProperty(property));
27494 Assert(fullmatrix->get_property() ==
27495 LAPACKSupport::Property::general,
27496 ExcInvalidLAPACKFullMatrixProperty(
27497 fullmatrix->get_property()));
27498
27499 Vector<Number> local_y(n);
27500 Vector<Number> local_x(m);
27501
27506 for (size_type j = 0; j < m; j++)
27507 {
27508 local_x(j) =
27509 x((*row_index_range)[0] -
27510 (*starting_hmat.row_index_range)[0] + j);
27511 }
27512
27513 fullmatrix->Hvmult(local_y, local_x);
27514
27518 for (size_type i = 0; i < n; i++)
27519 {
27520 y((*col_index_range)[0] -
27521 (*starting_hmat.col_index_range)[0] + i) +=
27522 alpha * local_y(i);
27523 }
27524
27525 Vector<Number> local_y_for_vmult(m);
27526 Vector<Number> local_x_for_vmult(n);
27527
27531 for (size_type j = 0; j < n; j++)
27532 {
27533 local_x_for_vmult(j) =
27534 x((*col_index_range)[0] -
27535 (*starting_hmat.col_index_range)[0] + j);
27536 }
27537
27538 fullmatrix->vmult(local_y_for_vmult,
27539 local_x_for_vmult);
27540
27544 for (size_type i = 0; i < m; i++)
27545 {
27546 y((*row_index_range)[0] -
27547 (*starting_hmat.row_index_range)[0] + i) +=
27548 alpha * local_y_for_vmult(i);
27549 }
27550
27551 break;
27552 }
27553 case HMatrixSupport::BlockType::
27554 upper_triangular_block: {
27562 break;
27563 }
27564 default: {
27565 throw(ExcInvalidHMatrixBlockType(block_type));
27566
27567 break;
27568 }
27569 }
27570
27571 break;
27572 }
27573 case HMatrixSupport::Property::lower_triangular: {
27579 switch (block_type)
27580 {
27581 case HMatrixSupport::BlockType::diagonal_block: {
27587 Assert(
27588 property ==
27589 HMatrixSupport::Property::lower_triangular,
27590 ExcInvalidHMatrixProperty(property));
27595 Assert(
27596 fullmatrix->get_property() ==
27597 LAPACKSupport::Property::lower_triangular,
27598 ExcInvalidLAPACKFullMatrixProperty(
27599 fullmatrix->get_property()));
27600
27605 Vector<Number> local_y(n);
27606 Vector<Number> local_x(m);
27607
27612 for (size_type j = 0; j < m; j++)
27613 {
27614 local_x(j) =
27615 x((*row_index_range)[0] -
27616 (*starting_hmat.row_index_range)[0] + j);
27617 }
27618
27619 fullmatrix->Hvmult(local_y, local_x);
27620
27624 for (size_type i = 0; i < n; i++)
27625 {
27626 y((*col_index_range)[0] -
27627 (*starting_hmat.col_index_range)[0] + i) +=
27628 alpha * local_y(i);
27629 }
27630
27631 break;
27632 }
27633 case HMatrixSupport::BlockType::
27634 lower_triangular_block: {
27640 Assert(property ==
27641 HMatrixSupport::Property::general,
27642 ExcInvalidHMatrixProperty(property));
27643 Assert(fullmatrix->get_property() ==
27644 LAPACKSupport::Property::general,
27645 ExcInvalidLAPACKFullMatrixProperty(
27646 fullmatrix->get_property()));
27647
27648 Vector<Number> local_y(n);
27649 Vector<Number> local_x(m);
27650
27655 for (size_type j = 0; j < m; j++)
27656 {
27657 local_x(j) =
27658 x((*row_index_range)[0] -
27659 (*starting_hmat.row_index_range)[0] + j);
27660 }
27661
27662 fullmatrix->Hvmult(local_y, local_x);
27663
27667 for (size_type i = 0; i < n; i++)
27668 {
27669 y((*col_index_range)[0] -
27670 (*starting_hmat.col_index_range)[0] + i) +=
27671 alpha * local_y(i);
27672 }
27673
27674 break;
27675 }
27676 case HMatrixSupport::BlockType::
27677 upper_triangular_block: {
27684 break;
27685 }
27686 default: {
27687 throw(ExcInvalidHMatrixBlockType(block_type));
27688
27689 break;
27690 }
27691 }
27692
27693 break;
27694 }
27695 case HMatrixSupport::Property::upper_triangular: {
27701 switch (block_type)
27702 {
27703 case HMatrixSupport::BlockType::diagonal_block: {
27709 Assert(
27710 property ==
27711 HMatrixSupport::Property::upper_triangular,
27712 ExcInvalidHMatrixProperty(property));
27717 Assert(
27718 fullmatrix->get_property() ==
27719 LAPACKSupport::Property::upper_triangular,
27720 ExcInvalidLAPACKFullMatrixProperty(
27721 fullmatrix->get_property()));
27722
27727 Vector<Number> local_y(n);
27728 Vector<Number> local_x(m);
27729
27734 for (size_type j = 0; j < m; j++)
27735 {
27736 local_x(j) =
27737 x((*row_index_range)[0] -
27738 (*starting_hmat.row_index_range)[0] + j);
27739 }
27740
27741 fullmatrix->Hvmult(local_y, local_x);
27742
27746 for (size_type i = 0; i < n; i++)
27747 {
27748 y((*col_index_range)[0] -
27749 (*starting_hmat.col_index_range)[0] + i) +=
27750 alpha * local_y(i);
27751 }
27752
27753 break;
27754 }
27755 case HMatrixSupport::BlockType::
27756 upper_triangular_block: {
27762 Assert(property ==
27763 HMatrixSupport::Property::general,
27764 ExcInvalidHMatrixProperty(property));
27765 Assert(fullmatrix->get_property() ==
27766 LAPACKSupport::Property::general,
27767 ExcInvalidLAPACKFullMatrixProperty(
27768 fullmatrix->get_property()));
27769
27770 Vector<Number> local_y(n);
27771 Vector<Number> local_x(m);
27772
27777 for (size_type j = 0; j < m; j++)
27778 {
27779 local_x(j) =
27780 x((*row_index_range)[0] -
27781 (*starting_hmat.row_index_range)[0] + j);
27782 }
27783
27784 fullmatrix->Hvmult(local_y, local_x);
27785
27789 for (size_type i = 0; i < n; i++)
27790 {
27791 y((*col_index_range)[0] -
27792 (*starting_hmat.col_index_range)[0] + i) +=
27793 alpha * local_y(i);
27794 }
27795
27796 break;
27797 }
27798 case HMatrixSupport::BlockType::
27799 lower_triangular_block: {
27804 break;
27805 }
27806 default: {
27807 throw(ExcInvalidHMatrixBlockType(block_type));
27808
27809 break;
27810 }
27811 }
27812
27813 break;
27814 }
27815 default: {
27816 throw(ExcInvalidHMatrixProperty(top_hmat_property));
27817
27818 break;
27819 }
27820 }
27821
27822 break;
27823 }
27824 case RkMatrixType: {
27829 switch (top_hmat_property)
27830 {
27831 case HMatrixSupport::Property::general: {
27836 Assert(property == HMatrixSupport::Property::general,
27837 ExcInvalidHMatrixProperty(property));
27838
27839 Vector<Number> local_y(n);
27840 Vector<Number> local_x(m);
27841
27845 for (size_type j = 0; j < m; j++)
27846 {
27847 local_x(j) =
27848 x((*row_index_range)[0] -
27849 (*starting_hmat.row_index_range)[0] + j);
27850 }
27851
27852 rkmatrix->Hvmult(local_y, local_x);
27853
27857 for (size_type i = 0; i < n; i++)
27858 {
27859 y((*col_index_range)[0] -
27860 (*starting_hmat.col_index_range)[0] + i) +=
27861 alpha * local_y(i);
27862 }
27863
27864 break;
27865 }
27866 case HMatrixSupport::Property::symmetric: {
27872 switch (block_type)
27873 {
27874 case HMatrixSupport::BlockType::diagonal_block: {
27879 throw(ExcInvalidHMatrixBlockType(block_type));
27880
27881 break;
27882 }
27883 case HMatrixSupport::BlockType::
27884 lower_triangular_block: {
27898 Assert(property ==
27899 HMatrixSupport::Property::general,
27900 ExcInvalidHMatrixProperty(property));
27901
27902 Vector<Number> local_y(n);
27903 Vector<Number> local_x(m);
27904
27908 for (size_type j = 0; j < m; j++)
27909 {
27910 local_x(j) =
27911 x((*row_index_range)[0] -
27912 (*starting_hmat.row_index_range)[0] + j);
27913 }
27914
27915 rkmatrix->Hvmult(local_y, local_x);
27916
27920 for (size_type i = 0; i < n; i++)
27921 {
27922 y((*col_index_range)[0] -
27923 (*starting_hmat.col_index_range)[0] + i) +=
27924 alpha * local_y(i);
27925 }
27926
27927 Vector<Number> local_y_for_vmult(m);
27928 Vector<Number> local_x_for_vmult(n);
27929
27933 for (size_type j = 0; j < n; j++)
27934 {
27935 local_x_for_vmult(j) =
27936 x((*col_index_range)[0] -
27937 (*starting_hmat.col_index_range)[0] + j);
27938 }
27939
27940 rkmatrix->Cvmult(local_y_for_vmult,
27941 local_x_for_vmult);
27942
27946 for (size_type i = 0; i < m; i++)
27947 {
27948 y((*row_index_range)[0] -
27949 (*starting_hmat.row_index_range)[0] + i) +=
27950 alpha * local_y_for_vmult(i);
27951 }
27952
27953 break;
27954 }
27955 case HMatrixSupport::BlockType::
27956 upper_triangular_block: {
27961 break;
27962 }
27963 default: {
27964 throw(ExcInvalidHMatrixBlockType(block_type));
27965
27966 break;
27967 }
27968 }
27969
27970 break;
27971 }
27972 case HMatrixSupport::Property::hermite_symmetric: {
27978 switch (block_type)
27979 {
27980 case HMatrixSupport::BlockType::diagonal_block: {
27985 throw(ExcInvalidHMatrixBlockType(block_type));
27986
27987 break;
27988 }
27989 case HMatrixSupport::BlockType::
27990 lower_triangular_block: {
28004 Assert(property ==
28005 HMatrixSupport::Property::general,
28006 ExcInvalidHMatrixProperty(property));
28007
28008 Vector<Number> local_y(n);
28009 Vector<Number> local_x(m);
28010
28014 for (size_type j = 0; j < m; j++)
28015 {
28016 local_x(j) =
28017 x((*row_index_range)[0] -
28018 (*starting_hmat.row_index_range)[0] + j);
28019 }
28020
28021 rkmatrix->Hvmult(local_y, local_x);
28022
28026 for (size_type i = 0; i < n; i++)
28027 {
28028 y((*col_index_range)[0] -
28029 (*starting_hmat.col_index_range)[0] + i) +=
28030 alpha * local_y(i);
28031 }
28032
28033 Vector<Number> local_y_for_vmult(m);
28034 Vector<Number> local_x_for_vmult(n);
28035
28039 for (size_type j = 0; j < n; j++)
28040 {
28041 local_x_for_vmult(j) =
28042 x((*col_index_range)[0] -
28043 (*starting_hmat.col_index_range)[0] + j);
28044 }
28045
28046 rkmatrix->vmult(local_y_for_vmult,
28047 local_x_for_vmult);
28048
28052 for (size_type i = 0; i < m; i++)
28053 {
28054 y((*row_index_range)[0] -
28055 (*starting_hmat.row_index_range)[0] + i) +=
28056 alpha * local_y_for_vmult(i);
28057 }
28058
28059 break;
28060 }
28061 case HMatrixSupport::BlockType::
28062 upper_triangular_block: {
28067 break;
28068 }
28069 default: {
28070 throw(ExcInvalidHMatrixBlockType(block_type));
28071
28072 break;
28073 }
28074 }
28075
28076 break;
28077 }
28078 case HMatrixSupport::Property::lower_triangular: {
28084 switch (block_type)
28085 {
28086 case HMatrixSupport::BlockType::diagonal_block: {
28091 throw(ExcInvalidHMatrixBlockType(block_type));
28092
28093 break;
28094 }
28095 case HMatrixSupport::BlockType::
28096 lower_triangular_block: {
28102 Assert(property ==
28103 HMatrixSupport::Property::general,
28104 ExcInvalidHMatrixProperty(property));
28105
28106 Vector<Number> local_y(n);
28107 Vector<Number> local_x(m);
28108
28112 for (size_type j = 0; j < m; j++)
28113 {
28114 local_x(j) =
28115 x((*row_index_range)[0] -
28116 (*starting_hmat.row_index_range)[0] + j);
28117 }
28118
28119 rkmatrix->Hvmult(local_y, local_x);
28120
28124 for (size_type i = 0; i < n; i++)
28125 {
28126 y((*col_index_range)[0] -
28127 (*starting_hmat.col_index_range)[0] + i) +=
28128 alpha * local_y(i);
28129 }
28130
28131 break;
28132 }
28133 case HMatrixSupport::BlockType::
28134 upper_triangular_block: {
28139 break;
28140 }
28141 default: {
28142 throw(ExcInvalidHMatrixBlockType(block_type));
28143
28144 break;
28145 }
28146 }
28147
28148 break;
28149 }
28150 case HMatrixSupport::Property::upper_triangular: {
28156 switch (block_type)
28157 {
28158 case HMatrixSupport::BlockType::diagonal_block: {
28163 throw(ExcInvalidHMatrixBlockType(block_type));
28164
28165 break;
28166 }
28167 case HMatrixSupport::BlockType::
28168 upper_triangular_block: {
28174 Assert(property ==
28175 HMatrixSupport::Property::general,
28176 ExcInvalidHMatrixProperty(property));
28177
28178 Vector<Number> local_y(n);
28179 Vector<Number> local_x(m);
28180
28184 for (size_type j = 0; j < m; j++)
28185 {
28186 local_x(j) =
28187 x((*row_index_range)[0] -
28188 (*starting_hmat.row_index_range)[0] + j);
28189 }
28190
28191 rkmatrix->Hvmult(local_y, local_x);
28192
28196 for (size_type i = 0; i < n; i++)
28197 {
28198 y((*col_index_range)[0] -
28199 (*starting_hmat.col_index_range)[0] + i) +=
28200 alpha * local_y(i);
28201 }
28202
28203 break;
28204 }
28205 case HMatrixSupport::BlockType::
28206 lower_triangular_block: {
28211 break;
28212 }
28213 default: {
28214 throw(ExcInvalidHMatrixBlockType(block_type));
28215
28216 break;
28217 }
28218 }
28219
28220 break;
28221 }
28222 default: {
28223 throw(ExcInvalidHMatrixProperty(top_hmat_property));
28224
28225 break;
28226 }
28227 }
28228
28229 break;
28230 }
28232 default: {
28233 Assert(false, ExcInvalidHMatrixType(type));
28234 break;
28235 }
28236 }
28237 }
28238 else
28239 {
28240 this->Tvmult(y, alpha, x, starting_hmat, top_hmat_property);
28241 }
28242}
28243
28244
28245template <int spacedim, typename Number>
28246template <typename Number2, typename Number3>
28247void
28249 const Number2 beta,
28250 Vector<Number> &y,
28251 const Number3 alpha,
28252 const Vector<Number> &x) const
28253{
28254 static_assert(is_number_larger_or_equal<Number, Number2>());
28255 static_assert(is_number_larger_or_equal<Number, Number3>());
28259 Assert(parent == nullptr, ExcInternalError());
28260
28261 if constexpr (numbers::NumberTraits<Number>::is_complex)
28262 {
28263 if (property == HMatrixSupport::Property::hermite_symmetric)
28264 {
28265 vmult_serial_iterative(beta, y, alpha, x);
28266 }
28267 else
28268 {
28272 y *= beta;
28273
28277 for (size_type l = 0; l < leaf_set.size(); l++)
28278 {
28279 const size_type m = this->leaf_set[l]->m;
28280 const size_type n = this->leaf_set[l]->n;
28281
28282 Vector<Number> local_y_for_Hvmult(n);
28283 Vector<Number> local_x_for_Hvmult(m);
28284
28289 for (size_type i = 0; i < m; i++)
28290 {
28291 local_x_for_Hvmult(i) =
28292 x((*this->leaf_set[l]->row_index_range)[0] + i);
28293 }
28294
28295 switch (this->leaf_set[l]->type)
28296 {
28298 this->leaf_set[l]->fullmatrix->Hvmult(local_y_for_Hvmult,
28299 local_x_for_Hvmult);
28300
28301 break;
28302 }
28304 this->leaf_set[l]->rkmatrix->Hvmult(local_y_for_Hvmult,
28305 local_x_for_Hvmult);
28306
28307 break;
28308 }
28309 default: {
28310 Assert(false,
28311 ExcInvalidHMatrixType(this->leaf_set[l]->type));
28312
28313 break;
28314 }
28315 }
28316
28321 for (size_type j = 0; j < n; j++)
28322 {
28323 y((*this->leaf_set[l]->col_index_range)[0] + j) +=
28324 alpha * local_y_for_Hvmult(j);
28325 }
28326
28327 if (this->property == HMatrixSupport::Property::symmetric &&
28328 this->leaf_set[l]->block_type ==
28329 HMatrixSupport::BlockType::lower_triangular_block)
28330 {
28335 Vector<Number> local_y(m);
28336 Vector<Number> local_x(n);
28337
28341 for (size_type j = 0; j < n; j++)
28342 {
28343 local_x(j) =
28344 x((*this->leaf_set[l]->col_index_range)[0] + j);
28345 }
28346
28347 switch (this->leaf_set[l]->type)
28348 {
28350 this->leaf_set[l]->fullmatrix->Cvmult(local_y,
28351 local_x);
28352
28353 break;
28354 }
28356 this->leaf_set[l]->rkmatrix->Cvmult(local_y, local_x);
28357
28358 break;
28359 }
28360 default: {
28361 Assert(false,
28362 ExcInvalidHMatrixType(
28363 this->leaf_set[l]->type));
28364
28365 break;
28366 }
28367 }
28368
28372 for (size_type i = 0; i < m; i++)
28373 {
28374 y((*this->leaf_set[l]->row_index_range)[0] + i) +=
28375 alpha * local_y(i);
28376 }
28377 }
28378 }
28379 }
28380 }
28381 else
28382 {
28383 this->Tvmult_serial_iterative(beta, y, alpha, x);
28384 }
28385}
28386
28387
28388template <int spacedim, typename Number>
28389template <typename Number2, typename Number3>
28390void
28392 Vector<Number> &y,
28393 const Number3 alpha,
28394 const Vector<Number> &x) const
28395{
28396 static_assert(is_number_larger_or_equal<Number, Number2>());
28397 static_assert(is_number_larger_or_equal<Number, Number3>());
28401 Assert(parent == nullptr, ExcInternalError());
28402
28403 if constexpr (numbers::NumberTraits<Number>::is_complex)
28404 {
28405 if (property == HMatrixSupport::Property::hermite_symmetric)
28406 {
28407 vmult_task_parallel(beta, y, alpha, x);
28408 }
28409 else
28410 {
28411 const unsigned int thread_num =
28412 data_for_vmult_or_tvmult_threads->size();
28413
28418 if (thread_num > 1)
28419 {
28420 // Set OpenBLAS num threads to 1 when task parallelization is
28421 // used.
28422 const int blas_num_threads = openblas_get_num_threads();
28423 openblas_set_num_threads(1);
28424
28430 auto local_scale_and_multiplication =
28431 [this, beta, alpha, &y, &x](
28432 const unsigned int thread_no) -> void {
28436 for (size_type i =
28437 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28438 .tvmult_result_index_range[0];
28439 i < (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28440 .tvmult_result_index_range[1];
28441 i++)
28442 {
28443 y[i] *= beta;
28444 }
28445
28450 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28451 .local_tvmult_result = Number(0.);
28452 if (this->property == HMatrixSupport::Property::symmetric)
28453 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28454 .local_vmult_result = Number(0.);
28455
28460 for (unsigned int l =
28461 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28462 .leaf_set_interval.first;
28463 l <= (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28464 .leaf_set_interval.second;
28465 l++)
28466 {
28467 const size_type m = this->leaf_set[l]->m;
28468 const size_type n = this->leaf_set[l]->n;
28469
28470 Vector<Number> local_y_for_Hvmult(n);
28471 Vector<Number> local_x_for_Hvmult(m);
28472
28476 for (size_type i = 0; i < m; i++)
28477 {
28478 local_x_for_Hvmult(i) =
28479 x((*this->leaf_set[l]->row_index_range)[0] + i);
28480 }
28481
28482 switch (this->leaf_set[l]->type)
28483 {
28485 this->leaf_set[l]->fullmatrix->Hvmult(
28486 local_y_for_Hvmult, local_x_for_Hvmult);
28487
28488 break;
28489 }
28491 this->leaf_set[l]->rkmatrix->Hvmult(
28492 local_y_for_Hvmult, local_x_for_Hvmult);
28493
28494 break;
28495 }
28496 default: {
28497 Assert(false,
28498 ExcInvalidHMatrixType(
28499 this->leaf_set[l]->type));
28500
28501 break;
28502 }
28503 }
28504
28510 for (size_type j = 0; j < n; j++)
28511 {
28512 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28513 .local_tvmult_result(
28514 (*this->leaf_set[l]->col_index_range)[0] -
28515 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28516 .local_tvmult_result_index_range[0] +
28517 j) += alpha * local_y_for_Hvmult(j);
28518 }
28519
28520 if (this->property == HMatrixSupport::Property::symmetric &&
28521 this->leaf_set[l]->block_type ==
28522 HMatrixSupport::BlockType::lower_triangular_block)
28523 {
28528 Vector<Number> local_y(m);
28529 Vector<Number> local_x(n);
28530
28534 for (size_type j = 0; j < n; j++)
28535 {
28536 local_x(j) =
28537 x((*this->leaf_set[l]->col_index_range)[0] + j);
28538 }
28539
28540 switch (this->leaf_set[l]->type)
28541 {
28543 this->leaf_set[l]->fullmatrix->Cvmult(local_y,
28544 local_x);
28545
28546 break;
28547 }
28549 this->leaf_set[l]->rkmatrix->Cvmult(local_y,
28550 local_x);
28551
28552 break;
28553 }
28554 default: {
28555 Assert(false,
28556 ExcInvalidHMatrixType(
28557 this->leaf_set[l]->type));
28558
28559 break;
28560 }
28561 }
28562
28568 for (size_type i = 0; i < m; i++)
28569 {
28570 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28571 .local_vmult_result(
28572 (*this->leaf_set[l]->row_index_range)[0] -
28573 (*this->data_for_vmult_or_tvmult_threads)
28574 [thread_no]
28575 .local_vmult_result_index_range[0] +
28576 i) += alpha * local_y(i);
28577 }
28578 }
28579 }
28580 };
28581
28582 Threads::TaskGroup<void> local_scaling_and_multiplication_tasks;
28583 for (unsigned int i = 0; i < thread_num; i++)
28584 {
28585 local_scaling_and_multiplication_tasks += Threads::new_task(
28586 std::bind(local_scale_and_multiplication, i));
28587 }
28588
28589 local_scaling_and_multiplication_tasks.join_all();
28590
28591 auto assemble_contribution_from_all_threads =
28592 [this, &y](const unsigned int thread_no) -> void {
28593 unsigned int other_thread_no = 0;
28594 for (
28595 const auto &range_intersection :
28596 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28597 .tvmult_result_index_ranges_contributed_from_other_threads)
28598 {
28599 for (size_type i = range_intersection[0];
28600 i < range_intersection[1];
28601 i++)
28602 {
28603 y(i) +=
28604 (*this->data_for_vmult_or_tvmult_threads)
28605 [other_thread_no]
28606 .local_tvmult_result(
28607 i - (*this->data_for_vmult_or_tvmult_threads)
28608 [other_thread_no]
28609 .local_tvmult_result_index_range[0]);
28610 }
28611
28612 other_thread_no++;
28613 }
28614
28615 if (this->property == HMatrixSupport::Property::symmetric)
28616 {
28617 unsigned int other_thread_no = 0;
28618 for (
28619 const auto &range_intersection :
28620 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
28621 .vmult_result_index_ranges_contributed_from_other_threads)
28622 {
28623 for (size_type i = range_intersection[0];
28624 i < range_intersection[1];
28625 i++)
28626 {
28627 y(i) +=
28628 (*this->data_for_vmult_or_tvmult_threads)
28629 [other_thread_no]
28630 .local_vmult_result(
28631 i -
28632 (*this->data_for_vmult_or_tvmult_threads)
28633 [other_thread_no]
28634 .local_vmult_result_index_range[0]);
28635 }
28636
28637 other_thread_no++;
28638 }
28639 }
28640 };
28641
28642 Threads::TaskGroup<void> assembly_tasks;
28643 for (unsigned int i = 0; i < thread_num; i++)
28644 {
28645 assembly_tasks += Threads::new_task(
28646 std::bind(assemble_contribution_from_all_threads, i));
28647 }
28648
28649 assembly_tasks.join_all();
28650
28651 // Restore the original OpenBLAS num threads.
28652 openblas_set_num_threads(blas_num_threads);
28653 }
28654 else
28655 {
28656 Hvmult_serial_iterative(beta, y, alpha, x);
28657 }
28658 }
28659 }
28660 else
28661 {
28662 Tvmult_task_parallel(beta, y, alpha, x);
28663 }
28664}
28665
28666
28667template <int spacedim, typename Number>
28668void
28670 const Vector<Number> &x) const
28671{
28672 if (!vmult_strategy)
28673 {
28674 Assert(false, ExcInternalError());
28675 }
28676 else
28677 vmult_strategy->Hvmult(y, *this, x);
28678}
28679
28680
28681template <int spacedim, typename Number>
28682void
28684 const Vector<Number> &x) const
28685{
28686 if (!vmult_strategy)
28687 {
28688 Assert(false, ExcInternalError());
28689 }
28690 else
28691 vmult_strategy->Hvmult_add(y, *this, x);
28692}
28693
28694
28695template <int spacedim, typename Number>
28696template <typename Number2>
28697void
28699 const Number2 alpha,
28700 const Vector<Number> &x) const
28701{
28702 if (!vmult_strategy)
28703 {
28704 Assert(false, ExcInternalError());
28705 }
28706 else
28707 vmult_strategy->Hvmult(y, alpha, *this, x);
28708}
28709
28710
28711template <int spacedim, typename Number>
28712template <typename Number2>
28713void
28715 const Number2 alpha,
28716 const Vector<Number> &x) const
28717{
28718 if (!vmult_strategy)
28719 {
28720 Assert(false, ExcInternalError());
28721 }
28722 else
28723 vmult_strategy->Hvmult_add(y, alpha, *this, x);
28724}
28725
28726
28727template <int spacedim, typename Number>
28728void
28730{
28731 std::vector<
28732 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>>
28733 Sigma_P_cannot_reduced;
28734
28735 while (Sigma_P.size() > 0)
28736 {
28737 // Get the last element in the list.
28738 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
28739 &hmat_pair = Sigma_P.back();
28740 HMatrix<spacedim, Number> *M1 = hmat_pair.first;
28741 HMatrix<spacedim, Number> *M2 = hmat_pair.second;
28742
28747 if (M1->type == RkMatrixType)
28748 {
28749 rk_h_mmult_for_h_h_mmult(M1, M2, this);
28750 }
28751 else if (M2->type == RkMatrixType)
28752 {
28753 h_rk_mmult_for_h_h_mmult(M1, M2, this);
28754 }
28755 else if (M1->type == FullMatrixType)
28756 {
28757 f_h_mmult_for_h_h_mmult(M1, M2, this);
28758 }
28759 else if (M2->type == FullMatrixType)
28760 {
28761 h_f_mmult_for_h_h_mmult(M1, M2, this);
28762 }
28763 else if (M1->bc_node->get_split_mode() == VerticalSplitMode &&
28764 M2->bc_node->get_split_mode() == HorizontalSplitMode)
28765 {
28766 // Internal splitting
28767 Sigma_P.pop_back();
28768
28769 Assert(M1->submatrices[0], ExcInternalError());
28770 Assert(M2->submatrices[0], ExcInternalError());
28771 Sigma_P.push_back(
28773 M1->submatrices[0], M2->submatrices[0]));
28774
28775 Assert(M1->submatrices[1], ExcInternalError());
28776 Assert(M2->submatrices[1], ExcInternalError());
28777 Sigma_P.push_back(
28779 M1->submatrices[1], M2->submatrices[1]));
28780 }
28781 else
28782 {
28787 Sigma_P_cannot_reduced.push_back(hmat_pair);
28793 Sigma_P.pop_back();
28794 }
28795 }
28796
28802 hmat_pair : Sigma_P_cannot_reduced)
28803 {
28804 Sigma_P.push_back(hmat_pair);
28805 }
28806}
28807
28808
28809template <int spacedim, typename Number>
28810void
28813{
28817 split_block_cluster_node(bc_node, bc_tree, HorizontalSplitMode);
28818
28820 InitHMatrixWrtBlockClusterNode(*child_hmat0, bc_node->get_child_pointer(0));
28825 submatrices.push_back(child_hmat0);
28826
28828 InitHMatrixWrtBlockClusterNode(*child_hmat1, bc_node->get_child_pointer(1));
28833 submatrices.push_back(child_hmat1);
28834
28838 while (Sigma_P.size() > 0)
28839 {
28840 // Get the last element in the list.
28841 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
28842 &hmat_pair = Sigma_P.back();
28843
28848 if (hmat_pair.first->bc_node->get_split_mode() == HorizontalSplitMode &&
28849 hmat_pair.second->bc_node->get_split_mode() == UnsplitMode)
28850 {
28851 Assert(hmat_pair.first->submatrices[0], ExcInternalError());
28852 child_hmat0->Sigma_P.push_back(
28854 hmat_pair.first->submatrices[0], hmat_pair.second));
28855
28856 Assert(hmat_pair.first->submatrices[1], ExcInternalError());
28857 child_hmat1->Sigma_P.push_back(
28859 hmat_pair.first->submatrices[1], hmat_pair.second));
28860
28865 Sigma_P.pop_back();
28866 }
28867 else if (hmat_pair.first->bc_node->get_split_mode() == CrossSplitMode &&
28868 hmat_pair.second->bc_node->get_split_mode() ==
28869 HorizontalSplitMode)
28870 {
28871 Assert(hmat_pair.first->submatrices[0], ExcInternalError());
28872 Assert(hmat_pair.second->submatrices[0], ExcInternalError());
28873 child_hmat0->Sigma_P.push_back(
28875 hmat_pair.first->submatrices[0],
28876 hmat_pair.second->submatrices[0]));
28877
28878 Assert(hmat_pair.first->submatrices[1], ExcInternalError());
28879 Assert(hmat_pair.second->submatrices[1], ExcInternalError());
28880 child_hmat0->Sigma_P.push_back(
28882 hmat_pair.first->submatrices[1],
28883 hmat_pair.second->submatrices[1]));
28884
28885 Assert(hmat_pair.first->submatrices[2], ExcInternalError());
28886 child_hmat1->Sigma_P.push_back(
28888 hmat_pair.first->submatrices[2],
28889 hmat_pair.second->submatrices[0]));
28890
28891 Assert(hmat_pair.first->submatrices[3], ExcInternalError());
28892 child_hmat1->Sigma_P.push_back(
28894 hmat_pair.first->submatrices[3],
28895 hmat_pair.second->submatrices[1]));
28896
28901 Sigma_P.pop_back();
28902 }
28903 else
28904 {
28905 Assert(false, ExcInternalError());
28906 }
28907 }
28908
28914}
28915
28916
28917template <int spacedim, typename Number>
28918void
28921{
28925 split_block_cluster_node(bc_node, bc_tree, VerticalSplitMode);
28926
28928 InitHMatrixWrtBlockClusterNode(*child_hmat0, bc_node->get_child_pointer(0));
28933 submatrices.push_back(child_hmat0);
28934
28936 InitHMatrixWrtBlockClusterNode(*child_hmat1, bc_node->get_child_pointer(1));
28941 submatrices.push_back(child_hmat1);
28942
28946 while (Sigma_P.size() > 0)
28947 {
28948 // Get the last element in the list.
28949 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
28950 &hmat_pair = Sigma_P.back();
28951
28956 if (hmat_pair.first->bc_node->get_split_mode() == UnsplitMode &&
28957 hmat_pair.second->bc_node->get_split_mode() == VerticalSplitMode)
28958 {
28959 Assert(hmat_pair.second->submatrices[0], ExcInternalError());
28960 child_hmat0->Sigma_P.push_back(
28962 hmat_pair.first, hmat_pair.second->submatrices[0]));
28963
28964 Assert(hmat_pair.second->submatrices[1], ExcInternalError());
28965 child_hmat1->Sigma_P.push_back(
28967 hmat_pair.first, hmat_pair.second->submatrices[1]));
28968
28973 Sigma_P.pop_back();
28974 }
28975 else if (hmat_pair.first->bc_node->get_split_mode() ==
28976 VerticalSplitMode &&
28977 hmat_pair.second->bc_node->get_split_mode() == CrossSplitMode)
28978 {
28979 Assert(hmat_pair.first->submatrices[0], ExcInternalError());
28980 Assert(hmat_pair.second->submatrices[0], ExcInternalError());
28981 child_hmat0->Sigma_P.push_back(
28983 hmat_pair.first->submatrices[0],
28984 hmat_pair.second->submatrices[0]));
28985
28986 Assert(hmat_pair.first->submatrices[1], ExcInternalError());
28987 Assert(hmat_pair.second->submatrices[2], ExcInternalError());
28988 child_hmat0->Sigma_P.push_back(
28990 hmat_pair.first->submatrices[1],
28991 hmat_pair.second->submatrices[2]));
28992
28993 Assert(hmat_pair.second->submatrices[1], ExcInternalError());
28994 child_hmat1->Sigma_P.push_back(
28996 hmat_pair.first->submatrices[0],
28997 hmat_pair.second->submatrices[1]));
28998
28999 Assert(hmat_pair.second->submatrices[3], ExcInternalError());
29000 child_hmat1->Sigma_P.push_back(
29002 hmat_pair.first->submatrices[1],
29003 hmat_pair.second->submatrices[3]));
29004
29009 Sigma_P.pop_back();
29010 }
29011 else
29012 {
29013 Assert(false, ExcInternalError());
29014 }
29015 }
29016
29022}
29023
29024
29025template <int spacedim, typename Number>
29026void
29029{
29033 split_block_cluster_node(bc_node, bc_tree, CrossSplitMode);
29034
29036 InitHMatrixWrtBlockClusterNode(*child_hmat0, bc_node->get_child_pointer(0));
29041 submatrices.push_back(child_hmat0);
29042
29044 InitHMatrixWrtBlockClusterNode(*child_hmat1, bc_node->get_child_pointer(1));
29049 submatrices.push_back(child_hmat1);
29050
29052 InitHMatrixWrtBlockClusterNode(*child_hmat2, bc_node->get_child_pointer(2));
29057 submatrices.push_back(child_hmat2);
29058
29060 InitHMatrixWrtBlockClusterNode(*child_hmat3, bc_node->get_child_pointer(3));
29065 submatrices.push_back(child_hmat3);
29066
29070 while (Sigma_P.size() > 0)
29071 {
29072 // Get the last element in the list.
29073 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
29074 &hmat_pair = Sigma_P.back();
29075
29080 if (hmat_pair.first->bc_node->get_split_mode() == CrossSplitMode &&
29081 hmat_pair.second->bc_node->get_split_mode() == CrossSplitMode)
29082 {
29088 Assert(hmat_pair.first->submatrices[0], ExcInternalError());
29089 Assert(hmat_pair.second->submatrices[0], ExcInternalError());
29090 child_hmat0->Sigma_P.push_back(
29092 hmat_pair.first->submatrices[0],
29093 hmat_pair.second->submatrices[0]));
29094
29095 Assert(hmat_pair.first->submatrices[1], ExcInternalError());
29096 Assert(hmat_pair.second->submatrices[2], ExcInternalError());
29097 child_hmat0->Sigma_P.push_back(
29099 hmat_pair.first->submatrices[1],
29100 hmat_pair.second->submatrices[2]));
29101
29107 Assert(hmat_pair.second->submatrices[1], ExcInternalError());
29108 child_hmat1->Sigma_P.push_back(
29110 hmat_pair.first->submatrices[0],
29111 hmat_pair.second->submatrices[1]));
29112
29113 Assert(hmat_pair.second->submatrices[3], ExcInternalError());
29114 child_hmat1->Sigma_P.push_back(
29116 hmat_pair.first->submatrices[1],
29117 hmat_pair.second->submatrices[3]));
29118
29124 Assert(hmat_pair.first->submatrices[2], ExcInternalError());
29125 child_hmat2->Sigma_P.push_back(
29127 hmat_pair.first->submatrices[2],
29128 hmat_pair.second->submatrices[0]));
29129
29130 Assert(hmat_pair.first->submatrices[3], ExcInternalError());
29131 child_hmat2->Sigma_P.push_back(
29133 hmat_pair.first->submatrices[3],
29134 hmat_pair.second->submatrices[2]));
29135
29141 child_hmat3->Sigma_P.push_back(
29143 hmat_pair.first->submatrices[2],
29144 hmat_pair.second->submatrices[1]));
29145
29146 child_hmat3->Sigma_P.push_back(
29148 hmat_pair.first->submatrices[3],
29149 hmat_pair.second->submatrices[3]));
29150
29155 Sigma_P.pop_back();
29156 }
29157 else if (hmat_pair.first->bc_node->get_split_mode() ==
29158 HorizontalSplitMode &&
29159 hmat_pair.second->bc_node->get_split_mode() == VerticalSplitMode)
29160 {
29161 Assert(hmat_pair.first->submatrices[0], ExcInternalError());
29162 Assert(hmat_pair.second->submatrices[0], ExcInternalError());
29163 child_hmat0->Sigma_P.push_back(
29165 hmat_pair.first->submatrices[0],
29166 hmat_pair.second->submatrices[0]));
29167
29168 Assert(hmat_pair.second->submatrices[1], ExcInternalError());
29169 child_hmat1->Sigma_P.push_back(
29171 hmat_pair.first->submatrices[0],
29172 hmat_pair.second->submatrices[1]));
29173
29174 Assert(hmat_pair.first->submatrices[1], ExcInternalError());
29175 child_hmat2->Sigma_P.push_back(
29177 hmat_pair.first->submatrices[1],
29178 hmat_pair.second->submatrices[0]));
29179
29180 child_hmat3->Sigma_P.push_back(
29182 hmat_pair.first->submatrices[1],
29183 hmat_pair.second->submatrices[1]));
29184
29189 Sigma_P.pop_back();
29190 }
29191 else
29192 {
29193 Assert(false, ExcInternalError());
29194 }
29195 }
29196
29202}
29203
29204
29205template <int spacedim, typename Number>
29206void
29213 const unsigned int fixed_rank)
29214{
29225 C.release();
29226
29232 bct_a.get_root()->get_data_reference().get_tau_node(),
29233 bct_b.get_root()->get_data_reference().get_sigma_node(),
29234 bct_c.get_n_min());
29235
29239 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
29240 initial_hmat_pair(this, &B);
29241 InitHMatrixWrtBlockClusterNode(C, C.Tind.get_root(), initial_hmat_pair);
29247
29253 C.Tind.build_leaf_set();
29256
29257 // /**
29258 // * DEBUG: Print the structure of the \f$T_{\rm ind}\f$ block cluster
29259 // tree.
29260 // */
29261 // std::ofstream out1("Tind_after_phase1.dat");
29262 // C.Tind.write_leaf_set(out1);
29263 // out1.close();
29264
29268 C.build_leaf_set();
29269
29270 // // DEBUG
29271 // std::cout << "=== Product matrix info before phase 2 ===" <<
29272 // std::endl; C.print_matrix_info(std::cout);
29273
29274 h_h_mmult_phase2(C, bct_c, fixed_rank);
29275
29276 // // DEBUG
29277 // std::cout << "=== Product matrix info after phase 2 ===" <<
29278 // std::endl; C.print_matrix_info(std::cout);
29279
29280 // /**
29281 // * DEBUG: Print the structure of the \f$T_{\rm ind}\f$ block cluster
29282 // tree.
29283 // */
29284 // std::ofstream out2("Tind_after_phase2.dat");
29285 // C.Tind.write_leaf_set(out2);
29286 // out2.close();
29287
29293}
29294
29295
29296template <int spacedim, typename Number>
29297void
29304 const unsigned int fixed_rank,
29305 const bool adding)
29306{
29307 if (adding)
29308 {
29310 mmult(C_prime, B, bct_a, bct_b, bct_c, fixed_rank);
29311 C.add(C_prime, fixed_rank);
29312 }
29313 else
29314 {
29315 mmult(C, B, bct_a, bct_b, bct_c, fixed_rank);
29316 }
29317}
29318
29319
29320template <int spacedim, typename Number>
29321void
29325 const unsigned int fixed_rank,
29326 const bool is_result_matrix_store_tril_only)
29327{
29329 C, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29330}
29331
29332
29333template <int spacedim, typename Number>
29334void
29337 const Number alpha,
29339 const unsigned int fixed_rank,
29340 const bool is_result_matrix_store_tril_only)
29341{
29343 C, alpha, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29344}
29345
29346
29347template <int spacedim, typename Number>
29348void
29351 const Number alpha,
29353 const unsigned int fixed_rank,
29354 const bool is_result_matrix_store_tril_only)
29355{
29357 C, alpha, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29358}
29359
29360
29361template <int spacedim, typename Number>
29362void
29366 const unsigned int fixed_rank,
29367 const bool is_result_matrix_store_tril_only)
29368{
29370 C, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29371}
29372
29373
29374template <int spacedim, typename Number>
29375void
29378 const Number alpha,
29380 const unsigned int fixed_rank,
29381 const bool is_result_matrix_store_tril_only)
29382{
29384 C, alpha, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29385}
29386
29387
29388template <int spacedim, typename Number>
29389void
29392 const Number alpha,
29394 const unsigned int fixed_rank,
29395 const bool is_result_matrix_store_tril_only)
29396{
29398 C, alpha, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29399}
29400
29401
29402template <int spacedim, typename Number>
29403void
29407 const unsigned int fixed_rank,
29408 const bool is_result_matrix_store_tril_only)
29409{
29411 C, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29412}
29413
29414
29415template <int spacedim, typename Number>
29416void
29419 const Number alpha,
29421 const unsigned int fixed_rank,
29422 const bool is_result_matrix_store_tril_only)
29423{
29425 C, alpha, (*this), B, fixed_rank, is_result_matrix_store_tril_only);
29426}
29427
29428
29429template <int spacedim, typename Number>
29430void
29433 const size_type fixed_rank_k) const
29434{
29439 switch (type)
29440 {
29445 for (size_type i = 0; i < submatrices.size(); i++)
29446 {
29447 submatrices[i]->add(*(C.submatrices[i]),
29448 *(B.submatrices[i]),
29449 fixed_rank_k);
29450 }
29451
29452 break;
29453 }
29454 case FullMatrixType: {
29458 this->fullmatrix->add(*(C.fullmatrix), *(B.fullmatrix));
29459
29460 break;
29461 }
29462 case RkMatrixType: {
29466 this->rkmatrix->add(*(C.rkmatrix), *(B.rkmatrix), fixed_rank_k);
29467
29468 break;
29469 }
29471 Assert(false, ExcInvalidHMatrixType(type));
29472 break;
29473 }
29474}
29475
29476
29477template <int spacedim, typename Number>
29478void
29480 const Number b,
29482 const size_type fixed_rank_k) const
29483{
29488 switch (type)
29489 {
29494 for (size_type i = 0; i < submatrices.size(); i++)
29495 {
29496 submatrices[i]->add(*(C.submatrices[i]),
29497 b,
29498 *(B.submatrices[i]),
29499 fixed_rank_k);
29500 }
29501
29502 break;
29503 }
29504 case FullMatrixType: {
29508 this->fullmatrix->add(*(C.fullmatrix), b, *(B.fullmatrix));
29509
29510 break;
29511 }
29512 case RkMatrixType: {
29516 this->rkmatrix->add(*(C.rkmatrix), b, *(B.rkmatrix), fixed_rank_k);
29517
29518 break;
29519 }
29521 Assert(false, ExcInvalidHMatrixType(type));
29522 break;
29523 }
29524}
29525
29526
29527template <int spacedim, typename Number>
29528void
29530 const size_type fixed_rank_k) const
29531{
29536 switch (type)
29537 {
29542 for (size_type i = 0; i < submatrices.size(); i++)
29543 {
29544 submatrices[i]->add(*(B.submatrices[i]), fixed_rank_k);
29545 }
29546
29547 break;
29548 }
29549 case FullMatrixType: {
29553 this->fullmatrix->add(*(B.fullmatrix));
29554
29555 break;
29556 }
29557 case RkMatrixType: {
29561 this->rkmatrix->add(*(B.rkmatrix), fixed_rank_k);
29562
29563 break;
29564 }
29566 Assert(false, ExcInvalidHMatrixType(type));
29567 break;
29568 }
29569}
29570
29571
29572template <int spacedim, typename Number>
29573void
29576 const size_type fixed_rank_k) const
29577{
29582 switch (type)
29583 {
29588 for (size_type i = 0; i < submatrices.size(); i++)
29589 {
29590 submatrices[i]->add(b, *(B.submatrices[i]), fixed_rank_k);
29591 }
29592
29593 break;
29594 }
29595 case FullMatrixType: {
29599 this->fullmatrix->add(b, *(B.fullmatrix));
29600
29601 break;
29602 }
29603 case RkMatrixType: {
29607 this->rkmatrix->add(b, *(B.rkmatrix), fixed_rank_k);
29608
29609 break;
29610 }
29612 Assert(false, ExcInvalidHMatrixType(type));
29613 break;
29614 }
29615}
29616
29617
29618template <int spacedim, typename Number>
29619void
29621 const RkMatrix<Number> &B,
29622 const std::array<types::global_dof_index, 2> &B_row_index_range,
29623 const std::array<types::global_dof_index, 2> &B_col_index_range,
29624 const size_type fixed_rank_k,
29625 const bool is_result_matrix_store_tril_only) const
29626{
29627 if (is_result_matrix_store_tril_only)
29628 {
29634 Assert(this->property == HMatrixSupport::Property::symmetric ||
29635 this->property == HMatrixSupport::Property::hermite_symmetric ||
29636 this->property == HMatrixSupport::Property::lower_triangular,
29637 ExcInvalidHMatrixProperty(this->property));
29638 Assert(this->block_type == HMatrixSupport::BlockType::diagonal_block,
29639 ExcInvalidHMatrixBlockType(this->block_type));
29640 }
29641
29642 switch (type)
29643 {
29656 if (is_result_matrix_store_tril_only)
29657 {
29658 for (size_type i = 0; i < submatrices.size(); i++)
29659 {
29660 if (submatrices[i]->block_type !=
29661 HMatrixSupport::BlockType::upper_triangular_block)
29662 {
29663 submatrices[i]->add(
29664 B,
29665 B_row_index_range,
29666 B_col_index_range,
29667 fixed_rank_k,
29668 submatrices[i]->property ==
29669 HMatrixSupport::Property::symmetric ||
29670 submatrices[i]->property ==
29671 HMatrixSupport::Property::hermite_symmetric ||
29672 submatrices[i]->property ==
29673 HMatrixSupport::Property::lower_triangular);
29674 }
29675 }
29676 }
29677 else
29678 {
29679 for (size_type i = 0; i < submatrices.size(); i++)
29680 {
29681 submatrices[i]->add(B,
29682 B_row_index_range,
29683 B_col_index_range,
29684 fixed_rank_k,
29685 false);
29686 }
29687 }
29688
29689 break;
29690 }
29691 case FullMatrixType: {
29703 LAPACKFullMatrixExt<Number> fullmatrix_from_rk;
29704 B.restrictToFullMatrix(B_row_index_range,
29705 B_col_index_range,
29706 fullmatrix_from_rk,
29707 *(row_index_range),
29708 *(col_index_range));
29709
29716 fullmatrix->add((const LAPACKFullMatrixExt<Number> &)
29717 fullmatrix_from_rk,
29718 is_result_matrix_store_tril_only);
29719
29720 break;
29721 }
29722 case RkMatrixType: {
29733 Assert(!is_result_matrix_store_tril_only, ExcInternalError());
29734
29739 RkMatrix<Number> rkmatrix_by_restriction(*(row_index_range),
29740 *(col_index_range),
29741 B,
29742 B_row_index_range,
29743 B_col_index_range);
29744
29745 this->rkmatrix->add(rkmatrix_by_restriction, fixed_rank_k);
29746
29747 break;
29748 }
29750 Assert(false, ExcInvalidHMatrixType(type));
29751 break;
29752 }
29753}
29754
29755
29756template <int spacedim, typename Number>
29757void
29759 const RkMatrix<Number> &B,
29760 const std::array<types::global_dof_index, 2> &B_row_index_range,
29761 const std::array<types::global_dof_index, 2> &B_col_index_range,
29762 const size_type fixed_rank_k,
29763 const bool is_result_matrix_store_tril_only)
29764{
29765 if (is_result_matrix_store_tril_only)
29766 {
29771 Assert(this->property == HMatrixSupport::Property::symmetric ||
29772 this->property == HMatrixSupport::Property::lower_triangular,
29773 ExcInvalidHMatrixProperty(this->property));
29774 Assert(this->block_type == HMatrixSupport::BlockType::diagonal_block,
29775 ExcInvalidHMatrixBlockType(this->block_type));
29776 }
29777
29778 switch (type)
29779 {
29792 if (is_result_matrix_store_tril_only)
29793 {
29794 for (size_type i = 0; i < submatrices.size(); i++)
29795 {
29796 if (submatrices[i]->block_type !=
29797 HMatrixSupport::BlockType::upper_triangular_block)
29798 {
29805 submatrices[i]->add_for_parallel_lu_or_cholesky(
29806 B,
29807 B_row_index_range,
29808 B_col_index_range,
29809 fixed_rank_k,
29810 submatrices[i]->property ==
29811 HMatrixSupport::Property::symmetric ||
29812 submatrices[i]->property ==
29813 HMatrixSupport::Property::lower_triangular);
29814 }
29815 }
29816 }
29817 else
29818 {
29819 for (size_type i = 0; i < submatrices.size(); i++)
29820 {
29827 submatrices[i]->add_for_parallel_lu_or_cholesky(
29828 B,
29829 B_row_index_range,
29830 B_col_index_range,
29831 fixed_rank_k,
29832 false);
29833 }
29834 }
29835
29836 break;
29837 }
29838 case FullMatrixType: {
29850 LAPACKFullMatrixExt<Number> fullmatrix_from_rk;
29851 B.restrictToFullMatrix(B_row_index_range,
29852 B_col_index_range,
29853 fullmatrix_from_rk,
29854 *(row_index_range),
29855 *(col_index_range));
29856
29857 {
29862 std::lock_guard<std::mutex> lg(update_lock);
29869 fullmatrix->add((const LAPACKFullMatrixExt<Number> &)
29870 fullmatrix_from_rk,
29871 is_result_matrix_store_tril_only);
29872 }
29873
29874 break;
29875 }
29876 case RkMatrixType: {
29887 Assert(!is_result_matrix_store_tril_only, ExcInternalError());
29888
29893 RkMatrix<Number> rkmatrix_by_restriction(*(row_index_range),
29894 *(col_index_range),
29895 B,
29896 B_row_index_range,
29897 B_col_index_range);
29898
29899 {
29904 std::lock_guard<std::mutex> lg(update_lock);
29905
29906#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 3
29907 this->rkmatrix->add(rkmatrix_by_restriction, fixed_rank_k);
29908#endif
29909
29910
29911#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 1
29912 tbb::task_arena ta{ARENA_MAX_CONCURRENCY_IN_LU_AND_CHOL};
29913 ta.execute([this, &rkmatrix_by_restriction, fixed_rank_k] {
29914 this->rkmatrix->add(rkmatrix_by_restriction, fixed_rank_k);
29915 });
29916#endif
29917
29918#if ARENA_OR_ISOLATE_IN_LU_AND_CHOL == 2
29923 tbb::this_task_arena::isolate(
29924 [this, &rkmatrix_by_restriction, fixed_rank_k] {
29925 this->rkmatrix->add(rkmatrix_by_restriction, fixed_rank_k);
29926 });
29927#endif
29928 }
29929
29930 break;
29931 }
29933 Assert(false, ExcInvalidHMatrixType(type));
29934 break;
29935 }
29936}
29937
29938
29939template <int spacedim, typename Number>
29940void
29942 const Number b,
29943 const RkMatrix<Number> &B,
29944 const std::array<types::global_dof_index, 2> &B_row_index_range,
29945 const std::array<types::global_dof_index, 2> &B_col_index_range,
29946 const size_type fixed_rank_k,
29947 const bool is_result_matrix_store_tril_only) const
29948{
29949 if (is_result_matrix_store_tril_only)
29950 {
29955 Assert(this->property == HMatrixSupport::Property::symmetric ||
29956 this->property == HMatrixSupport::Property::hermite_symmetric ||
29957 this->property == HMatrixSupport::Property::lower_triangular,
29958 ExcInvalidHMatrixProperty(this->property));
29959 Assert(this->block_type == HMatrixSupport::BlockType::diagonal_block,
29960 ExcInvalidHMatrixBlockType(this->block_type));
29961 }
29962
29963 switch (type)
29964 {
29972 if (is_result_matrix_store_tril_only)
29973 {
29974 for (size_type i = 0; i < submatrices.size(); i++)
29975 {
29976 if (submatrices[i]->block_type !=
29977 HMatrixSupport::BlockType::upper_triangular_block)
29978 {
29979 submatrices[i]->add(
29980 b,
29981 B,
29982 B_row_index_range,
29983 B_col_index_range,
29984 fixed_rank_k,
29985 submatrices[i]->property ==
29986 HMatrixSupport::Property::symmetric ||
29987 submatrices[i]->property ==
29988 HMatrixSupport::Property::hermite_symmetric ||
29989 submatrices[i]->property ==
29990 HMatrixSupport::Property::lower_triangular);
29991 }
29992 }
29993 }
29994 else
29995 {
29996 for (size_type i = 0; i < submatrices.size(); i++)
29997 {
29998 submatrices[i]->add(b,
29999 B,
30000 B_row_index_range,
30001 B_col_index_range,
30002 fixed_rank_k,
30003 false);
30004 }
30005 }
30006
30007 break;
30008 }
30009 case FullMatrixType: {
30021 LAPACKFullMatrixExt<Number> fullmatrix_from_rk;
30022 B.restrictToFullMatrix(B_row_index_range,
30023 B_col_index_range,
30024 fullmatrix_from_rk,
30025 *(row_index_range),
30026 *(col_index_range));
30027
30028 this->fullmatrix->add(b,
30030 fullmatrix_from_rk,
30031 is_result_matrix_store_tril_only);
30032
30033 break;
30034 }
30035 case RkMatrixType: {
30049 RkMatrix<Number> rkmatrix_by_restriction(*(row_index_range),
30050 *(col_index_range),
30051 B,
30052 B_row_index_range,
30053 B_col_index_range);
30054
30055 this->rkmatrix->add(b, rkmatrix_by_restriction, fixed_rank_k);
30056
30057 break;
30058 }
30060 Assert(false, ExcInvalidHMatrixType(type));
30061 break;
30062 }
30063}
30064
30065
30066template <int spacedim, typename Number>
30067void
30069 const size_type fixed_rank_k,
30070 const bool is_result_matrix_store_tril_only)
30071{
30072 AssertDimension(m, B.get_m());
30073 AssertDimension(n, B.get_n());
30074
30075 this->add(B,
30076 *row_index_range,
30077 *col_index_range,
30078 fixed_rank_k,
30079 is_result_matrix_store_tril_only);
30080}
30081
30082
30083template <int spacedim, typename Number>
30084void
30086 const RkMatrix<Number> &B,
30087 const size_type fixed_rank_k,
30088 const bool is_result_matrix_store_tril_only)
30089{
30090 AssertDimension(m, B.get_m());
30091 AssertDimension(n, B.get_n());
30092
30093 this->add_for_parallel_lu_or_cholesky(B,
30094 *row_index_range,
30095 *col_index_range,
30096 fixed_rank_k,
30097 is_result_matrix_store_tril_only);
30098}
30099
30100
30101template <int spacedim, typename Number>
30102void
30104 const RkMatrix<Number> &B,
30105 const size_type fixed_rank_k,
30106 const bool is_result_matrix_store_tril_only)
30107{
30108 AssertDimension(m, B.get_m());
30109 AssertDimension(n, B.get_n());
30110
30111 this->add(b,
30112 B,
30113 *row_index_range,
30114 *col_index_range,
30115 fixed_rank_k,
30116 is_result_matrix_store_tril_only);
30117}
30118
30119
30120template <int spacedim, typename Number>
30121void
30123{
30124 if (E.m() != 0 && E.n() != 0)
30125 {
30135 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
30136 ExcMessage(
30137 "The current H-matrix node should be a diagonal block!"));
30138
30139 if (type == FullMatrixType)
30140 {
30147 E.mTmult(EEH, E);
30148
30149 this->fullmatrix->add(EEH);
30150 }
30151 else
30152 {
30157 Assert(type == HierarchicalMatrixType, ExcInvalidHMatrixType(type));
30158
30159 std::array<types::global_dof_index, 2> &t1_index_range =
30160 *(submatrices[0]->row_index_range);
30161 std::array<types::global_dof_index, 2> &t2_index_range =
30162 *(submatrices[3]->row_index_range);
30163
30164 LAPACKFullMatrixExt<Number> E1(t1_index_range[1] - t1_index_range[0],
30165 E.n());
30166 LAPACKFullMatrixExt<Number> E2(t2_index_range[1] - t2_index_range[0],
30167 E.n());
30168
30173 for (size_type i = 0; i < E1.m(); i++)
30174 {
30175 E1.fill_row(i,
30176 t1_index_range[0] - (*this->row_index_range)[0] + i,
30177 E,
30178 std::sqrt(2.0));
30179 }
30180
30185 for (size_type i = 0; i < E2.m(); i++)
30186 {
30187 E2.fill_row(i,
30188 t2_index_range[0] - (*this->row_index_range)[0] + i,
30189 E,
30190 std::sqrt(2.0));
30191 }
30192
30193 submatrices[0]->addsym_diag(E1);
30194 submatrices[3]->addsym_diag(E2);
30195 }
30196 }
30197}
30198
30199
30200template <int spacedim, typename Number>
30201void
30203 const RkMatrix<Number> &B,
30204 const size_type fixed_rank_k)
30205{
30206 C = (*this);
30207 C.add(B, fixed_rank_k);
30208}
30209
30210
30211template <int spacedim, typename Number>
30212void
30214 const Number b,
30215 const RkMatrix<Number> &B,
30216 const size_type fixed_rank_k)
30217{
30218 C = (*this);
30219 C.add(b, B, fixed_rank_k);
30220}
30221
30222
30223template <int spacedim, typename Number>
30224void
30227 const size_type fixed_rank_k)
30228{
30229 _invert_by_gauss_elim(M_inv, fixed_rank_k);
30230
30234 build_leaf_set();
30235 link_hmat_nodes_on_same_levels();
30236
30237 M_inv.build_leaf_set();
30239}
30240
30241
30242template <int spacedim, typename Number>
30243void
30245 Vector<Number> &b,
30246 const bool is_unit_diagonal) const
30247{
30251 AssertDimension(m, n);
30252
30253 if (type != HierarchicalMatrixType)
30254 {
30259 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
30260 Assert(fullmatrix != nullptr, ExcInternalError());
30261
30262 Vector<Number> local_b(n);
30263
30267 for (size_type j = 0; j < n; j++)
30268 {
30269 local_b(j) = b((*col_index_range)[0] + j);
30270 }
30271
30278 fullmatrix->solve_by_forward_substitution(
30279 local_b,
30280 false, // Is transposed
30281 is_unit_diagonal,
30282 true // Is the RHS vector permuted, which should be true when the
30283 // matrix has been applied LU factorization.
30284 );
30285
30289 for (size_type i = 0; i < m; i++)
30290 {
30291 b((*row_index_range)[0] + i) = local_b(i);
30292 }
30293 }
30294 else
30295 {
30296 const unsigned int n_row_blocks = get_n_row_blocks();
30297 const unsigned int n_col_blocks = get_n_col_blocks();
30298
30299 AssertDimension(n_row_blocks, n_col_blocks);
30300
30304 for (size_type i = 0; i < n_row_blocks; i++)
30305 {
30310 for (size_type j = 0; j < i; j++)
30311 {
30312 submatrices[i * n_col_blocks + j]->vmult(
30313 b, real_type(-1.0), b, HMatrixSupport::Property::general);
30314 }
30315
30320 submatrices[i * n_col_blocks + i]->solve_by_forward_substitution(
30321 b, is_unit_diagonal);
30322 }
30323 }
30324}
30325
30326
30327template <int spacedim, typename Number>
30328void
30330 Vector<Number> &x,
30331 const Vector<Number> &b,
30332 const bool is_unit_diagonal) const
30333{
30334 x = b;
30335 solve_by_forward_substitution(x, is_unit_diagonal);
30336}
30337
30338
30339
30340template <int spacedim, typename Number>
30341void
30343 Vector<Number> &b,
30344 const HMatrix<spacedim, Number> &starting_hmat,
30345 const bool is_unit_diagonal) const
30346{
30350 AssertDimension(m, n);
30351
30352 if (type != HierarchicalMatrixType)
30353 {
30358 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
30359 Assert(fullmatrix != nullptr, ExcInternalError());
30360
30361 Vector<Number> local_b(n);
30362
30366 for (size_type j = 0; j < n; j++)
30367 {
30368 local_b(j) =
30369 b((*col_index_range)[0] - (*starting_hmat.col_index_range)[0] + j);
30370 }
30371
30378 fullmatrix->solve_by_forward_substitution(
30379 local_b,
30380 false, // Is transposed
30381 is_unit_diagonal,
30382 true // Is the RHS vector permuted, which should be true when the
30383 // matrix has been applied LU factorization.
30384 );
30385
30389 for (size_type i = 0; i < m; i++)
30390 {
30391 b((*row_index_range)[0] - (*starting_hmat.row_index_range)[0] + i) =
30392 local_b(i);
30393 }
30394 }
30395 else
30396 {
30400 const unsigned int n_row_blocks = get_n_row_blocks();
30401 const unsigned int n_col_blocks = get_n_col_blocks();
30402
30403 AssertDimension(n_row_blocks, n_col_blocks);
30404
30405 for (size_type i = 0; i < n_row_blocks; i++)
30406 {
30411 for (size_type j = 0; j < i; j++)
30412 {
30413 submatrices[i * n_col_blocks + j]->vmult(
30414 b,
30415 real_type(-1.0),
30416 b,
30417 starting_hmat,
30418 HMatrixSupport::Property::general);
30419 }
30420
30425 submatrices[i * n_col_blocks + i]->solve_by_forward_substitution(
30426 b, starting_hmat, is_unit_diagonal);
30427 }
30428 }
30429}
30430
30431
30432template <int spacedim, typename Number>
30433void
30435 Vector<Number> &x,
30436 const Vector<Number> &b,
30437 const HMatrix<spacedim, Number> &starting_hmat,
30438 const bool is_unit_diagonal) const
30439{
30440 x = b;
30441 solve_by_forward_substitution(x, starting_hmat, is_unit_diagonal);
30442}
30443
30444
30445template <int spacedim, typename Number>
30446void
30450 const unsigned int fixed_rank,
30451 const bool is_unit_diagonal) const
30452{
30453 AssertDimension(Z.m, X.m);
30454 AssertDimension(Z.n, X.n);
30455 Assert(
30456 Z.type == X.type,
30457 ExcMessage(
30458 "Matrix Z and X should be built on a same block cluster and thus they should have a same H-matrix type!"));
30459 AssertDimension(this->m, this->n);
30460 AssertDimension(this->n, X.m);
30461
30462 if (Z.type == FullMatrixType)
30463 {
30468 Vector<Number> X_col(X.m);
30469 Vector<Number> Z_col(Z.m);
30470
30474 for (size_type j = 0; j < Z.n; j++)
30475 {
30476 Z.fullmatrix->get_column(j, Z_col);
30477
30483 this->solve_by_forward_substitution(X_col,
30484 Z_col,
30485 (*this),
30486 is_unit_diagonal);
30487
30492 X.fullmatrix->fill_col(j, X_col);
30493 }
30494 }
30495 else if (Z.type == RkMatrixType)
30496 {
30514 (*X.rkmatrix) = (*Z.rkmatrix);
30515
30516 Vector<Number> A_prime_col(X.m);
30517 for (size_type j = 0; j < Z.rkmatrix->get_formal_rank(); j++)
30518 {
30519 Z.rkmatrix->get_A().get_column(j, A_prime_col);
30520
30521 this->solve_by_forward_substitution(A_prime_col,
30522 (*this),
30523 is_unit_diagonal);
30524
30528 X.rkmatrix->get_A().fill_col(j, A_prime_col);
30529 }
30530 }
30531 else
30532 {
30543 AssertDimension(
30544 this->get_n_row_blocks(),
30545 this->bc_node->get_data_reference().get_sigma_node()->get_child_num());
30546
30552 const unsigned int n_row_blocks = X.get_n_row_blocks();
30553 AssertDimension(this->get_n_row_blocks(), n_row_blocks);
30558 const unsigned int n_col_blocks = X.get_n_col_blocks();
30559
30564 AssertDimension(n_row_blocks, Z.get_n_row_blocks());
30565 AssertDimension(n_col_blocks, Z.get_n_col_blocks());
30566
30570 for (size_type i = 0; i < n_row_blocks; i++)
30571 {
30578 for (size_type j = 0; j < n_col_blocks; j++)
30579 {
30584 for (size_type k = 0; k < i; k++)
30585 {
30586 this->submatrices[i * n_row_blocks + k]
30587 ->mmult_level_conserving(
30588 *(Z.submatrices[i * n_col_blocks + j]),
30589 -1.0,
30590 *(X.submatrices[k * n_col_blocks + j]),
30591 fixed_rank);
30592 }
30593
30598 this->submatrices[i * n_row_blocks + i]
30599 ->solve_by_forward_substitution_matrix_valued(
30600 *(X.submatrices[i * n_col_blocks + j]),
30601 *(Z.submatrices[i * n_col_blocks + j]),
30602 fixed_rank,
30603 is_unit_diagonal);
30604 }
30605 }
30606 }
30607}
30608
30609
30610template <int spacedim, typename Number>
30611void
30614 const unsigned int fixed_rank,
30615 const bool is_unit_diagonal) const
30616{
30617 AssertDimension(this->m, this->n);
30618 AssertDimension(this->n, Z.m);
30619
30620 if (Z.type == FullMatrixType)
30621 {
30626 Vector<Number> Z_col(Z.m);
30627
30631 for (size_type j = 0; j < Z.n; j++)
30632 {
30633 Z.fullmatrix->get_column(j, Z_col);
30634
30640 this->solve_by_forward_substitution(Z_col, (*this), is_unit_diagonal);
30641
30645 Z.fullmatrix->fill_col(j, Z_col);
30646 }
30647 }
30648 else if (Z.type == RkMatrixType)
30649 {
30667 Vector<Number> A_prime_col(Z.m);
30668 for (size_type j = 0; j < Z.rkmatrix->get_formal_rank(); j++)
30669 {
30670 Z.rkmatrix->get_A().get_column(j, A_prime_col);
30671
30672 this->solve_by_forward_substitution(A_prime_col,
30673 (*this),
30674 is_unit_diagonal);
30675
30679 Z.rkmatrix->get_A().fill_col(j, A_prime_col);
30680 }
30681 }
30682 else
30683 {
30694 AssertDimension(
30695 this->get_n_row_blocks(),
30696 this->bc_node->get_data_reference().get_sigma_node()->get_child_num());
30697
30703 const unsigned int n_row_blocks = Z.get_n_row_blocks();
30704 AssertDimension(this->get_n_row_blocks(), n_row_blocks);
30709 const unsigned int n_col_blocks = Z.get_n_col_blocks();
30710
30714 for (size_type i = 0; i < n_row_blocks; i++)
30715 {
30722 for (size_type j = 0; j < n_col_blocks; j++)
30723 {
30728 for (size_type k = 0; k < i; k++)
30729 {
30730 this->submatrices[i * n_row_blocks + k]
30731 ->mmult_level_conserving(
30732 *(Z.submatrices[i * n_col_blocks + j]),
30733 -1.0,
30734 *(Z.submatrices[k * n_col_blocks + j]),
30735 fixed_rank);
30736 }
30737
30742 this->submatrices[i * n_row_blocks + i]
30743 ->solve_by_forward_substitution_matrix_valued(
30744 *(Z.submatrices[i * n_col_blocks + j]),
30745 fixed_rank,
30746 is_unit_diagonal);
30747 }
30748 }
30749 }
30750}
30751
30752
30753template <int spacedim, typename Number>
30754void
30758 const unsigned int fixed_rank) const
30759{
30760 solve_by_forward_substitution_matrix_valued(X, Z, fixed_rank, false);
30761}
30762
30763
30764template <int spacedim, typename Number>
30765void
30768 const unsigned int fixed_rank) const
30769{
30770 solve_by_forward_substitution_matrix_valued(Z, fixed_rank, false);
30771}
30772
30773
30774template <int spacedim, typename Number>
30775void
30777 Vector<Number> &b) const
30778{
30782 AssertDimension(m, n);
30783
30784 if (type != HierarchicalMatrixType)
30785 {
30791 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
30792 Assert(fullmatrix != nullptr, ExcInternalError());
30793
30794 Vector<Number> local_b(m);
30795
30799 for (size_type i = 0; i < m; i++)
30800 {
30801 local_b(i) = b((*row_index_range)[0] + i);
30802 }
30803
30808 fullmatrix->solve_by_forward_substitution(local_b, true, false, false);
30809
30813 for (size_type j = 0; j < n; j++)
30814 {
30815 b((*col_index_range)[0] + j) = local_b(j);
30816 }
30817 }
30818 else
30819 {
30820 const unsigned int n_col_blocks = get_n_col_blocks();
30821
30822 AssertDimension(get_n_row_blocks(), n_col_blocks);
30823
30828 for (size_type j = 0; j < n_col_blocks; j++)
30829 {
30834 for (size_type i = 0; i < j; i++)
30835 {
30836 submatrices[i * n_col_blocks + j]->Tvmult(
30837 b, real_type(-1.0), b, HMatrixSupport::Property::general);
30838 }
30839
30844 submatrices[j * n_col_blocks + j]
30845 ->solve_transpose_by_forward_substitution(b);
30846 }
30847 }
30848}
30849
30850
30851template <int spacedim, typename Number>
30852void
30854 Vector<Number> &x,
30855 const Vector<Number> &b) const
30856{
30857 x = b;
30858 solve_transpose_by_forward_substitution(x);
30859}
30860
30861
30862template <int spacedim, typename Number>
30863void
30865 Vector<Number> &b,
30866 const HMatrix<spacedim, Number> &starting_hmat) const
30867{
30871 AssertDimension(m, n);
30872
30873 if (type != HierarchicalMatrixType)
30874 {
30880 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
30881 Assert(fullmatrix != nullptr, ExcInternalError());
30882
30883 Vector<Number> local_b(m);
30884
30888 for (size_type i = 0; i < m; i++)
30889 {
30890 local_b(i) =
30891 b((*row_index_range)[0] - (*starting_hmat.row_index_range)[0] + i);
30892 }
30893
30898 fullmatrix->solve_by_forward_substitution(local_b, true, false, false);
30899
30903 for (size_type j = 0; j < n; j++)
30904 {
30905 b((*col_index_range)[0] - (*starting_hmat.col_index_range)[0] + j) =
30906 local_b(j);
30907 }
30908 }
30909 else
30910 {
30911 const unsigned int n_col_blocks = get_n_col_blocks();
30912
30913 AssertDimension(get_n_row_blocks(), n_col_blocks);
30914
30919 for (size_type j = 0; j < n_col_blocks; j++)
30920 {
30925 for (size_type i = 0; i < j; i++)
30926 {
30927 submatrices[i * n_col_blocks + j]->Tvmult(
30928 b,
30929 real_type(-1.0),
30930 b,
30931 starting_hmat,
30932 HMatrixSupport::Property::general);
30933 }
30934
30939 submatrices[j * n_col_blocks + j]
30940 ->solve_transpose_by_forward_substitution(b, starting_hmat);
30941 }
30942 }
30943}
30944
30945
30946template <int spacedim, typename Number>
30947void
30949 Vector<Number> &x,
30950 const Vector<Number> &b,
30951 const HMatrix<spacedim, Number> &starting_hmat) const
30952{
30953 x = b;
30954 solve_transpose_by_forward_substitution(x, starting_hmat);
30955}
30956
30957
30958template <int spacedim, typename Number>
30959void
30964 const unsigned int fixed_rank) const
30965{
30966 AssertDimension(Z.m, X.m);
30967 AssertDimension(Z.n, X.n);
30968 Assert(
30969 Z.type == X.type,
30970 ExcMessage(
30971 "Matrix Z and X should be built on a same block cluster and thus have a same H-matrix type!"));
30972 AssertDimension(this->m, this->n);
30973 AssertDimension(X.n, this->m);
30974
30975 if (Z.type == FullMatrixType)
30976 {
30981 Vector<Number> X_row(X.n);
30982 Vector<Number> Z_row(Z.n);
30983
30987 for (size_type i = 0; i < Z.m; i++)
30988 {
30989 Z.fullmatrix->get_row(i, Z_row);
30990
30997 this->solve_transpose_by_forward_substitution(X_row, Z_row, (*this));
30998
31003 X.fullmatrix->fill_row(i, X_row);
31004 }
31005 }
31006 else if (Z.type == RkMatrixType)
31007 {
31008 (*X.rkmatrix) = (*Z.rkmatrix);
31009
31010 // Let \f$Z\vert_{\tau\times\sigma} = A\cdot B^T\f$ and
31011 // \f$X\vert_{\tau\times\sigma}=A\cdot B'^T\f$, solve the problem \f$U^T
31012 // B' = B\f$.
31013 Vector<Number> B_prime_col(X.n);
31014 for (size_type j = 0; j < Z.rkmatrix->get_formal_rank(); j++)
31015 {
31016 // Get the current RHS vector directly into the solution vector.
31017 Z.rkmatrix->get_B().get_column(j, B_prime_col);
31018
31023 this->solve_transpose_by_forward_substitution(B_prime_col, (*this));
31024
31030 X.rkmatrix->get_B().fill_col(j, B_prime_col);
31031 }
31032 }
31033 else
31034 {
31046 AssertDimension(
31047 this->get_n_row_blocks(),
31048 this->bc_node->get_data_reference().get_sigma_node()->get_child_num());
31049
31054 const unsigned int n_row_blocks = X.get_n_row_blocks();
31061 const unsigned int n_col_blocks = X.get_n_col_blocks();
31062 AssertDimension(this->get_n_row_blocks(), n_col_blocks);
31063
31070 AssertDimension(n_row_blocks, Z.get_n_row_blocks());
31071 AssertDimension(n_col_blocks, Z.get_n_col_blocks());
31072
31077 for (size_type j = 0; j < n_col_blocks; j++)
31078 {
31085 for (size_type i = 0; i < n_row_blocks; i++)
31086 {
31093 for (size_type k = 0; k < j; k++)
31094 {
31095 X.submatrices[i * n_col_blocks + k]->mmult_level_conserving(
31096 *(Z.submatrices[i * n_col_blocks + j]),
31097 -1.0,
31098 *(this->submatrices[k * n_col_blocks + j]),
31099 fixed_rank);
31100 }
31101
31106 this->submatrices[j * n_col_blocks + j]
31107 ->solve_transpose_by_forward_substitution_matrix_valued(
31108 *(X.submatrices[i * n_col_blocks + j]),
31109 *(Z.submatrices[i * n_col_blocks + j]),
31110 fixed_rank);
31111 }
31112 }
31113 }
31114}
31115
31116
31117template <int spacedim, typename Number>
31118void
31122 const unsigned int fixed_rank) const
31123{
31124 AssertDimension(this->m, this->n);
31125 AssertDimension(Z.n, this->m);
31126
31127 if (Z.type == FullMatrixType)
31128 {
31133 Vector<Number> Z_row(Z.n);
31134
31138 for (size_type i = 0; i < Z.m; i++)
31139 {
31140 Z.fullmatrix->get_row(i, Z_row);
31141
31148 this->solve_transpose_by_forward_substitution(Z_row, (*this));
31149
31153 Z.fullmatrix->fill_row(i, Z_row);
31154 }
31155 }
31156 else if (Z.type == RkMatrixType)
31157 {
31158 // Let \f$Z\vert_{\tau\times\sigma} = A\cdot B^T\f$ and
31159 // \f$X\vert_{\tau\times\sigma}=A\cdot B'^T\f$, solve the problem \f$U^T
31160 // B' = B\f$.
31161 Vector<Number> B_col(Z.n);
31162 for (size_type j = 0; j < Z.rkmatrix->get_formal_rank(); j++)
31163 {
31164 // Get the current RHS vector directly into the solution vector.
31165 Z.rkmatrix->get_B().get_column(j, B_col);
31166
31171 this->solve_transpose_by_forward_substitution(B_col, (*this));
31172
31176 Z.rkmatrix->get_B().fill_col(j, B_col);
31177 }
31178 }
31179 else
31180 {
31192 AssertDimension(
31193 this->get_n_row_blocks(),
31194 this->bc_node->get_data_reference().get_sigma_node()->get_child_num());
31195
31199 const unsigned int n_row_blocks = Z.get_n_row_blocks();
31205 const unsigned int n_col_blocks = Z.get_n_col_blocks();
31206 AssertDimension(this->get_n_row_blocks(), n_col_blocks);
31207
31212 for (size_type j = 0; j < n_col_blocks; j++)
31213 {
31220 for (size_type i = 0; i < n_row_blocks; i++)
31221 {
31228 for (size_type k = 0; k < j; k++)
31229 {
31230 Z.submatrices[i * n_col_blocks + k]->mmult_level_conserving(
31231 *(Z.submatrices[i * n_col_blocks + j]),
31232 -1.0,
31233 *(this->submatrices[k * n_col_blocks + j]),
31234 fixed_rank);
31235 }
31236
31241 this->submatrices[j * n_col_blocks + j]
31242 ->solve_transpose_by_forward_substitution_matrix_valued(
31243 *(Z.submatrices[i * n_col_blocks + j]), fixed_rank);
31244 }
31245 }
31246 }
31247}
31248
31249
31250template <int spacedim, typename Number>
31251void
31256 const unsigned int fixed_rank) const
31257{
31258 AssertDimension(Z.m, X.m);
31259 AssertDimension(Z.n, X.n);
31260 Assert(
31261 Z.type == X.type,
31262 ExcMessage(
31263 "Matrix Z and X should be built on a same block cluster and thus have a same H-matrix type!"));
31264 AssertDimension(this->m, this->n);
31272 AssertDimension(X.n, this->n);
31273
31274 if (Z.type == FullMatrixType)
31275 {
31280 Vector<Number> X_row(X.n);
31281 Vector<Number> Z_row(Z.n);
31282
31286 for (size_type i = 0; i < Z.m; i++)
31287 {
31288 Z.fullmatrix->get_row(i, Z_row);
31289
31297 this->solve_by_forward_substitution(X_row, Z_row, (*this), false);
31298
31303 X.fullmatrix->fill_row(i, X_row);
31304 }
31305 }
31306 else if (Z.type == RkMatrixType)
31307 {
31308 (*X.rkmatrix) = (*Z.rkmatrix);
31309
31310 Vector<Number> B_prime_col(X.n);
31311 for (size_type j = 0; j < Z.rkmatrix->get_formal_rank(); j++)
31312 {
31313 Z.rkmatrix->get_B().get_column(j, B_prime_col);
31314
31320 this->solve_by_forward_substitution(B_prime_col, (*this), false);
31321
31325 X.rkmatrix->get_B().fill_col(j, B_prime_col);
31326 }
31327 }
31328 else
31329 {
31340 AssertDimension(
31341 this->get_n_row_blocks(),
31342 this->bc_node->get_data_reference().get_sigma_node()->get_child_num());
31343
31348 const unsigned int n_row_blocks = X.get_n_row_blocks();
31355 const unsigned int n_col_blocks = X.get_n_col_blocks();
31356 AssertDimension(this->get_n_col_blocks(), n_col_blocks);
31357
31362 AssertDimension(n_row_blocks, Z.get_n_row_blocks());
31363 AssertDimension(n_col_blocks, Z.get_n_col_blocks());
31364
31370 for (size_type j = 0; j < n_col_blocks; j++)
31371 {
31378 for (size_type i = 0; i < n_row_blocks; i++)
31379 {
31391 for (size_type k = 0; k < j; k++)
31392 {
31393 X.submatrices[i * n_col_blocks + k]->mTmult_level_conserving(
31394 *(Z.submatrices[i * n_col_blocks + j]),
31395 -1.0,
31396 *(this->submatrices[j * n_col_blocks + k]),
31397 fixed_rank);
31398 }
31399
31405 this->submatrices[j * n_col_blocks + j]
31406 ->solve_cholesky_transpose_by_forward_substitution_matrix_valued(
31407 *(X.submatrices[i * n_col_blocks + j]),
31408 *(Z.submatrices[i * n_col_blocks + j]),
31409 fixed_rank);
31410 }
31411 }
31412 }
31413}
31414
31415
31416template <int spacedim, typename Number>
31417void
31421 const unsigned int fixed_rank) const
31422{
31423 AssertDimension(this->m, this->n);
31431 AssertDimension(Z.n, this->n);
31432
31433 if (Z.type == FullMatrixType)
31434 {
31439 Vector<Number> Z_row(Z.n);
31440
31444 for (size_type i = 0; i < Z.m; i++)
31445 {
31446 Z.fullmatrix->get_row(i, Z_row);
31447
31455 this->solve_by_forward_substitution(Z_row, (*this), false);
31456
31460 Z.fullmatrix->fill_row(i, Z_row);
31461 }
31462 }
31463 else if (Z.type == RkMatrixType)
31464 {
31465 Vector<Number> B_col(Z.n);
31466 for (size_type j = 0; j < Z.rkmatrix->get_formal_rank(); j++)
31467 {
31468 Z.rkmatrix->get_B().get_column(j, B_col);
31469
31475 this->solve_by_forward_substitution(B_col, (*this), false);
31476
31480 Z.rkmatrix->get_B().fill_col(j, B_col);
31481 }
31482 }
31483 else
31484 {
31495 AssertDimension(
31496 this->get_n_row_blocks(),
31497 this->bc_node->get_data_reference().get_sigma_node()->get_child_num());
31498
31502 const unsigned int n_row_blocks = Z.get_n_row_blocks();
31508 const unsigned int n_col_blocks = Z.get_n_col_blocks();
31509 AssertDimension(this->get_n_col_blocks(), n_col_blocks);
31510
31515 for (size_type j = 0; j < n_col_blocks; j++)
31516 {
31522 for (size_type i = 0; i < n_row_blocks; i++)
31523 {
31535 for (size_type k = 0; k < j; k++)
31536 {
31537 Z.submatrices[i * n_col_blocks + k]->mTmult_level_conserving(
31538 *(Z.submatrices[i * n_col_blocks + j]),
31539 -1.0,
31540 *(this->submatrices[j * n_col_blocks + k]),
31541 fixed_rank);
31542 }
31543
31549 this->submatrices[j * n_col_blocks + j]
31550 ->solve_cholesky_transpose_by_forward_substitution_matrix_valued(
31551 *(Z.submatrices[i * n_col_blocks + j]), fixed_rank);
31552 }
31553 }
31554 }
31555}
31556
31557
31558template <int spacedim, typename Number>
31559void
31561 Vector<Number> &b,
31562 const bool is_unit_block_diagonal) const
31563{
31567 AssertDimension(m, n);
31568
31569 if (type != HierarchicalMatrixType)
31570 {
31575 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
31576 Assert(fullmatrix != nullptr, ExcInternalError());
31577
31578 if (is_unit_block_diagonal)
31579 {
31585 }
31586 else
31587 {
31593 Vector<Number> local_b(n);
31594
31599 for (size_type j = 0; j < n; j++)
31600 {
31601 local_b(j) = b((*col_index_range)[0] + j);
31602 }
31603
31607 fullmatrix->compute_lu_factorization();
31608 fullmatrix->solve(local_b);
31609
31614 for (size_type i = 0; i < m; i++)
31615 {
31616 b((*row_index_range)[0] + i) = local_b(i);
31617 }
31618 }
31619 }
31620 else
31621 {
31625 const unsigned int n_row_blocks = get_n_row_blocks();
31626 const unsigned int n_col_blocks = get_n_col_blocks();
31627
31628 AssertDimension(n_row_blocks, n_col_blocks);
31629
31630 for (size_type i = 0; i < n_row_blocks; i++)
31631 {
31636 for (size_type j = 0; j < i; j++)
31637 {
31638 submatrices[i * n_col_blocks + j]->vmult(
31639 b, real_type(-1.0), b, HMatrixSupport::Property::general);
31640 }
31641
31646 submatrices[i * n_col_blocks + i]
31647 ->solve_block_triangular_by_forward_substitution(
31648 b, is_unit_block_diagonal);
31649 }
31650 }
31651}
31652
31653
31654template <int spacedim, typename Number>
31655void
31657 Vector<Number> &x,
31658 const Vector<Number> &b,
31659 const bool is_unit_block_diagonal) const
31660{
31661 x = b;
31662 solve_block_triangular_by_forward_substitution(x, is_unit_block_diagonal);
31663}
31664
31665
31666template <int spacedim, typename Number>
31667void
31669 Vector<Number> &b,
31670 const HMatrix<spacedim, Number> &starting_hmat,
31671 const bool is_unit_block_diagonal) const
31672{
31676 AssertDimension(m, n);
31677
31678 if (type != HierarchicalMatrixType)
31679 {
31684 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
31685 Assert(fullmatrix != nullptr, ExcInternalError());
31686
31687 if (is_unit_block_diagonal)
31688 {
31694 }
31695 else
31696 {
31702 Vector<Number> local_b(n);
31703
31708 for (size_type j = 0; j < n; j++)
31709 {
31710 local_b(j) = b((*col_index_range)[0] -
31711 (*starting_hmat.col_index_range)[0] + j);
31712 }
31713
31717 fullmatrix->compute_lu_factorization();
31718 fullmatrix->solve(local_b);
31719
31724 for (size_type i = 0; i < m; i++)
31725 {
31726 b((*row_index_range)[0] - (*starting_hmat.row_index_range)[0] +
31727 i) = local_b(i);
31728 }
31729 }
31730 }
31731 else
31732 {
31736 const unsigned int n_row_blocks = get_n_row_blocks();
31737 const unsigned int n_col_blocks = get_n_col_blocks();
31738
31739 AssertDimension(n_row_blocks, n_col_blocks);
31740
31741 for (size_type i = 0; i < n_row_blocks; i++)
31742 {
31747 for (size_type j = 0; j < i; j++)
31748 {
31749 submatrices[i * n_col_blocks + j]->vmult(
31750 b,
31751 real_type(-1.0),
31752 b,
31753 starting_hmat,
31754 HMatrixSupport::Property::general);
31755 }
31756
31761 submatrices[i * n_col_blocks + i]
31762 ->solve_block_triangular_by_forward_substitution(
31763 b, starting_hmat, is_unit_block_diagonal);
31764 }
31765 }
31766}
31767
31768
31769template <int spacedim, typename Number>
31770void
31772 Vector<Number> &x,
31773 const Vector<Number> &b,
31774 const HMatrix<spacedim, Number> &starting_hmat,
31775 const bool is_unit_block_diagonal) const
31776{
31777 x = b;
31778 solve_block_triangular_by_forward_substitution(x,
31779 starting_hmat,
31780 is_unit_block_diagonal);
31781}
31782
31783
31784template <int spacedim, typename Number>
31785void
31787 Vector<Number> &b) const
31788{
31789 Assert(state == HMatrixSupport::cholesky, ExcInvalidHMatrixState(state));
31790
31791 solve_by_forward_substitution(b, false);
31792}
31793
31794
31795template <int spacedim, typename Number>
31796void
31798 Vector<Number> &x,
31799 const Vector<Number> &b) const
31800{
31801 Assert(state == HMatrixSupport::cholesky, ExcInvalidHMatrixState(state));
31802
31803 solve_by_forward_substitution(x, b, false);
31804}
31805
31806
31807template <int spacedim, typename Number>
31808void
31810 Vector<Number> &b,
31811 const HMatrix<spacedim, Number> &starting_hmat) const
31812{
31813 Assert(state == HMatrixSupport::cholesky, ExcInvalidHMatrixState(state));
31814
31815 solve_by_forward_substitution(b, starting_hmat, false);
31816}
31817
31818
31819template <int spacedim, typename Number>
31820void
31822 Vector<Number> &x,
31823 const Vector<Number> &b,
31824 const HMatrix<spacedim, Number> &starting_hmat) const
31825{
31826 Assert(state == HMatrixSupport::cholesky, ExcInvalidHMatrixState(state));
31827
31828 solve_by_forward_substitution(x, b, starting_hmat, false);
31829}
31830
31831
31832template <int spacedim, typename Number>
31833void
31835 Vector<Number> &b,
31836 const bool is_unit_diagonal) const
31837{
31841 AssertDimension(m, n);
31842
31843 if (type != HierarchicalMatrixType)
31844 {
31849 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
31850 Assert(fullmatrix != nullptr, ExcInternalError());
31851
31852 Vector<Number> local_b(n);
31853
31857 for (size_type j = 0; j < n; j++)
31858 {
31859 local_b(j) = b((*col_index_range)[0] + j);
31860 }
31861
31865 fullmatrix->solve_by_backward_substitution(local_b,
31866 false, // Is transposed
31867 is_unit_diagonal);
31868
31872 for (size_type i = 0; i < m; i++)
31873 {
31874 b((*row_index_range)[0] + i) = local_b(i);
31875 }
31876 }
31877 else
31878 {
31882 const unsigned int n_row_blocks = get_n_row_blocks();
31883 const unsigned int n_col_blocks = get_n_col_blocks();
31884
31885 AssertDimension(n_row_blocks, n_col_blocks);
31886
31893 for (int i = n_row_blocks - 1; i >= 0; i--)
31894 {
31899 for (size_type j = i + 1; j < n_col_blocks; j++)
31900 {
31901 submatrices[i * n_col_blocks + j]->vmult(
31902 b, real_type(-1.0), b, HMatrixSupport::Property::general);
31903 }
31904
31909 submatrices[i * n_col_blocks + i]->solve_by_backward_substitution(
31910 b, is_unit_diagonal);
31911 }
31912 }
31913}
31914
31915
31916template <int spacedim, typename Number>
31917void
31919 Vector<Number> &x,
31920 const Vector<Number> &b,
31921 const bool is_unit_diagonal) const
31922{
31923 x = b;
31924 solve_by_backward_substitution(x, is_unit_diagonal);
31925}
31926
31927
31928template <int spacedim, typename Number>
31929void
31931 Vector<Number> &b,
31932 const HMatrix<spacedim, Number> &starting_hmat,
31933 const bool is_unit_diagonal) const
31934{
31938 AssertDimension(m, n);
31939
31940 if (type != HierarchicalMatrixType)
31941 {
31946 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
31947 Assert(fullmatrix != nullptr, ExcInternalError());
31948
31949 Vector<Number> local_b(n);
31950
31954 for (size_type j = 0; j < n; j++)
31955 {
31956 local_b(j) =
31957 b((*col_index_range)[0] - (*starting_hmat.col_index_range)[0] + j);
31958 }
31959
31963 fullmatrix->solve_by_backward_substitution(local_b,
31964 false, // Is transposed
31965 is_unit_diagonal);
31966
31970 for (size_type i = 0; i < m; i++)
31971 {
31972 b((*row_index_range)[0] - (*starting_hmat.row_index_range)[0] + i) =
31973 local_b(i);
31974 }
31975 }
31976 else
31977 {
31981 const unsigned int n_row_blocks = get_n_row_blocks();
31982 const unsigned int n_col_blocks = get_n_col_blocks();
31983
31984 AssertDimension(n_row_blocks, n_col_blocks);
31985
31992 for (int i = n_row_blocks - 1; i >= 0; i--)
31993 {
31998 for (size_type j = i + 1; j < n_col_blocks; j++)
31999 {
32000 submatrices[i * n_col_blocks + j]->vmult(
32001 b,
32002 real_type(-1.0),
32003 b,
32004 starting_hmat,
32005 HMatrixSupport::Property::general);
32006 }
32007
32011 submatrices[i * n_col_blocks + i]->solve_by_backward_substitution(
32012 b, starting_hmat, is_unit_diagonal);
32013 }
32014 }
32015}
32016
32017
32018template <int spacedim, typename Number>
32019void
32021 Vector<Number> &x,
32022 const Vector<Number> &b,
32023 const HMatrix<spacedim, Number> &starting_hmat,
32024 const bool is_unit_diagonal) const
32025{
32026 x = b;
32027 solve_by_backward_substitution(x, starting_hmat, is_unit_diagonal);
32028}
32029
32030
32031template <int spacedim, typename Number>
32032void
32034 Vector<Number> &b,
32035 const bool is_unit_block_diagonal) const
32036{
32040 AssertDimension(m, n);
32041
32042 if (type != HierarchicalMatrixType)
32043 {
32048 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
32049 Assert(fullmatrix != nullptr, ExcInternalError());
32050
32051 if (is_unit_block_diagonal)
32052 {
32058 }
32059 else
32060 {
32066 Vector<Number> local_b(n);
32067
32072 for (size_type j = 0; j < n; j++)
32073 {
32074 local_b(j) = b((*col_index_range)[0] + j);
32075 }
32076
32080 fullmatrix->compute_lu_factorization();
32081 fullmatrix->solve(local_b);
32082
32087 for (size_type i = 0; i < m; i++)
32088 {
32089 b((*row_index_range)[0] + i) = local_b(i);
32090 }
32091 }
32092 }
32093 else
32094 {
32098 const unsigned int n_row_blocks = get_n_row_blocks();
32099 const unsigned int n_col_blocks = get_n_col_blocks();
32100
32101 AssertDimension(n_row_blocks, n_col_blocks);
32102
32109 for (int i = n_row_blocks - 1; i >= 0; i--)
32110 {
32115 for (size_type j = i + 1; j < n_col_blocks; j++)
32116 {
32117 submatrices[i * n_col_blocks + j]->vmult(
32118 b, real_type(-1.0), b, HMatrixSupport::Property::general);
32119 }
32120
32124 submatrices[i * n_col_blocks + i]
32125 ->solve_block_triangular_by_backward_substitution(
32126 b, is_unit_block_diagonal);
32127 }
32128 }
32129}
32130
32131
32132template <int spacedim, typename Number>
32133void
32135 Vector<Number> &x,
32136 const Vector<Number> &b,
32137 const bool is_unit_block_diagonal) const
32138{
32139 x = b;
32140 solve_block_triangular_by_backward_substitution(x, is_unit_block_diagonal);
32141}
32142
32143
32144template <int spacedim, typename Number>
32145void
32147 Vector<Number> &b,
32148 const HMatrix<spacedim, Number> &starting_hmat,
32149 const bool is_unit_block_diagonal) const
32150{
32154 AssertDimension(m, n);
32155
32156 if (type != HierarchicalMatrixType)
32157 {
32162 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
32163 Assert(fullmatrix != nullptr, ExcInternalError());
32164
32165 if (is_unit_block_diagonal)
32166 {
32172 }
32173 else
32174 {
32180 Vector<Number> local_b(n);
32181
32186 for (size_type j = 0; j < n; j++)
32187 {
32188 local_b(j) = b((*col_index_range)[0] -
32189 (*starting_hmat.col_index_range)[0] + j);
32190 }
32191
32195 fullmatrix->compute_lu_factorization();
32196 fullmatrix->solve(local_b);
32197
32202 for (size_type i = 0; i < m; i++)
32203 {
32204 b((*row_index_range)[0] - (*starting_hmat.row_index_range)[0] +
32205 i) = local_b(i);
32206 }
32207 }
32208 }
32209 else
32210 {
32214 const unsigned int n_row_blocks = get_n_row_blocks();
32215 const unsigned int n_col_blocks = get_n_col_blocks();
32216
32217 AssertDimension(n_row_blocks, n_col_blocks);
32218
32225 for (int i = n_row_blocks - 1; i >= 0; i--)
32226 {
32231 for (size_type j = i + 1; j < n_col_blocks; j++)
32232 {
32233 submatrices[i * n_col_blocks + j]->vmult(
32234 b,
32235 real_type(-1.0),
32236 b,
32237 starting_hmat,
32238 HMatrixSupport::Property::general);
32239 }
32240
32244 submatrices[i * n_col_blocks + i]
32245 ->solve_block_triangular_by_backward_substitution(
32246 b, starting_hmat, is_unit_block_diagonal);
32247 }
32248 }
32249}
32250
32251
32252template <int spacedim, typename Number>
32253void
32255 Vector<Number> &x,
32256 const Vector<Number> &b,
32257 const HMatrix<spacedim, Number> &starting_hmat,
32258 const bool is_unit_block_diagonal) const
32259{
32260 x = b;
32261 solve_block_triangular_by_backward_substitution(x,
32262 starting_hmat,
32263 is_unit_block_diagonal);
32264}
32265
32266
32267template <int spacedim, typename Number>
32268void
32270 Vector<Number> &b) const
32271{
32272 Assert(state == HMatrixSupport::cholesky, ExcInvalidHMatrixState(state));
32273
32277 AssertDimension(m, n);
32278
32279 if (type != HierarchicalMatrixType)
32280 {
32285 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
32286 Assert(fullmatrix != nullptr, ExcInternalError());
32287
32288 Vector<Number> local_b(m);
32289
32295 for (size_type i = 0; i < m; i++)
32296 {
32297 local_b(i) = b((*row_index_range)[0] + i);
32298 }
32299
32306 fullmatrix->solve_by_backward_substitution(local_b,
32307 true, // Is transposed
32308 false // Is unit diagonal
32309 );
32310
32314 for (size_type j = 0; j < n; j++)
32315 {
32316 b((*col_index_range)[0] + j) = local_b(j);
32317 }
32318 }
32319 else
32320 {
32321 const unsigned int n_row_blocks = get_n_row_blocks();
32322 const unsigned int n_col_blocks = get_n_col_blocks();
32323
32324 AssertDimension(n_row_blocks, n_col_blocks);
32325
32329 for (int j = n_col_blocks - 1; j >= 0; j--)
32330 {
32335 for (size_type i = j + 1; i < n_row_blocks; i++)
32336 {
32341 submatrices[i * n_col_blocks + j]->Tvmult(
32342 b, real_type(-1.0), b, HMatrixSupport::Property::general);
32343 }
32344
32349 submatrices[j * n_col_blocks + j]
32350 ->solve_cholesky_by_backward_substitution(b);
32351 }
32352 }
32353}
32354
32355
32356template <int spacedim, typename Number>
32357void
32359 Vector<Number> &x,
32360 const Vector<Number> &b) const
32361{
32362 x = b;
32363 solve_cholesky_by_backward_substitution(x);
32364}
32365
32366
32367template <int spacedim, typename Number>
32368void
32370 Vector<Number> &b,
32371 const HMatrix<spacedim, Number> &starting_hmat) const
32372{
32376 AssertDimension(m, n);
32377
32378 if (type != HierarchicalMatrixType)
32379 {
32384 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
32385 Assert(fullmatrix != nullptr, ExcInternalError());
32386
32387 Vector<Number> local_b(m);
32388
32394 for (size_type i = 0; i < m; i++)
32395 {
32396 local_b(i) =
32397 b((*row_index_range)[0] - (*starting_hmat.row_index_range)[0] + i);
32398 }
32399
32404 fullmatrix->solve_by_backward_substitution(local_b,
32405 true, // Is transposed
32406 false // Is unit diagonal
32407 );
32408
32412 for (size_type j = 0; j < n; j++)
32413 {
32414 b((*col_index_range)[0] - (*starting_hmat.col_index_range)[0] + j) =
32415 local_b(j);
32416 }
32417 }
32418 else
32419 {
32420 const unsigned int n_row_blocks = get_n_row_blocks();
32421 const unsigned int n_col_blocks = get_n_col_blocks();
32422
32423 AssertDimension(n_row_blocks, n_col_blocks);
32424
32428 for (int j = n_col_blocks - 1; j >= 0; j--)
32429 {
32434 for (size_type i = j + 1; i < n_row_blocks; i++)
32435 {
32440 submatrices[i * n_col_blocks + j]->Tvmult(
32441 b,
32442 real_type(-1.0),
32443 b,
32444 starting_hmat,
32445 HMatrixSupport::Property::general);
32446 }
32447
32452 submatrices[j * n_col_blocks + j]
32453 ->solve_cholesky_by_backward_substitution(b, starting_hmat);
32454 }
32455 }
32456}
32457
32458
32459template <int spacedim, typename Number>
32460void
32462 Vector<Number> &x,
32463 const Vector<Number> &b,
32464 const HMatrix<spacedim, Number> &starting_hmat) const
32465{
32466 x = b;
32467 solve_cholesky_by_backward_substitution(x, starting_hmat);
32468}
32469
32470
32471template <int spacedim, typename Number>
32472void
32475 const unsigned int fixed_rank)
32476{
32477 this->_compute_lu_factorization(LU, fixed_rank);
32478
32483 LU.set_state(HMatrixSupport::lu);
32484 this->set_state(HMatrixSupport::unusable);
32485}
32486
32487
32488template <int spacedim, typename Number>
32489void
32491 const unsigned int fixed_rank)
32492{
32493 this->_compute_lu_factorization(fixed_rank);
32494
32498 this->set_state(HMatrixSupport::lu);
32499}
32500
32501
32502template <int spacedim, typename Number>
32503void
32506 const unsigned int fixed_rank) const
32507{
32508 if (type != HierarchicalMatrixType)
32509 {
32518 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
32519 Assert(fullmatrix != nullptr, ExcInternalError());
32520 Assert(LU.fullmatrix != nullptr, ExcInternalError());
32521
32525 *(LU.fullmatrix) = *fullmatrix;
32526
32531 LU.fullmatrix->compute_lu_factorization();
32532 }
32533 else
32534 {
32535 const unsigned int n_row_blocks = get_n_row_blocks();
32536 const unsigned int n_col_blocks = get_n_col_blocks();
32537
32542 AssertDimension(n_row_blocks, n_col_blocks);
32543
32548 for (size_type i = 0; i < n_row_blocks; i++)
32549 {
32553 for (size_type j = 0; j < n_col_blocks; j++)
32554 {
32562 const size_type min_ij = std::min(i, j);
32567 HMatrix<spacedim, Number> Z(*(submatrices[i * n_col_blocks + j]));
32568 for (size_type k = 0; k < min_ij; k++)
32569 {
32570 LU.submatrices[i * n_col_blocks + k]->mmult_level_conserving(
32571 Z,
32572 -1.0,
32573 *(LU.submatrices[k * n_col_blocks + j]),
32574 fixed_rank);
32575 }
32576
32577 if (j < i)
32578 {
32585 LU.submatrices[j * n_col_blocks + j]
32586 ->solve_transpose_by_forward_substitution_matrix_valued(
32587 *(LU.submatrices[i * n_col_blocks + j]), Z, fixed_rank);
32588 }
32589 else if (j == i)
32590 {
32596 *(LU.submatrices[i * n_col_blocks + i]), fixed_rank);
32597 }
32598 else if (j > i)
32599 {
32603 LU.submatrices[i * n_col_blocks + i]
32604 ->solve_by_forward_substitution_matrix_valued(
32605 *(LU.submatrices[i * n_col_blocks + j]), Z, fixed_rank);
32606 }
32607 }
32608 }
32609 }
32610}
32611
32612
32613template <int spacedim, typename Number>
32614void
32616 const unsigned int fixed_rank)
32617{
32618 if (type != HierarchicalMatrixType)
32619 {
32628 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
32629 Assert(fullmatrix != nullptr, ExcInternalError());
32630
32635 fullmatrix->compute_lu_factorization();
32636 }
32637 else
32638 {
32639 const unsigned int n_row_blocks = get_n_row_blocks();
32640 const unsigned int n_col_blocks = get_n_col_blocks();
32641
32646 AssertDimension(n_row_blocks, n_col_blocks);
32647
32652 for (size_type i = 0; i < n_row_blocks; i++)
32653 {
32657 for (size_type j = 0; j < n_col_blocks; j++)
32658 {
32666 const size_type min_ij = std::min(i, j);
32667
32668 for (size_type k = 0; k < min_ij; k++)
32669 {
32670 submatrices[i * n_col_blocks + k]->mmult_level_conserving(
32671 *(submatrices[i * n_col_blocks + j]),
32672 -1.0,
32673 *(submatrices[k * n_col_blocks + j]),
32674 fixed_rank);
32675 }
32676
32677 if (j < i)
32678 {
32685 submatrices[j * n_col_blocks + j]
32686 ->solve_transpose_by_forward_substitution_matrix_valued(
32687 *(submatrices[i * n_col_blocks + j]), fixed_rank);
32688 }
32689 else if (j == i)
32690 {
32695 submatrices[i * n_col_blocks + i]->_compute_lu_factorization(
32696 fixed_rank);
32697 }
32698 else if (j > i)
32699 {
32703 submatrices[i * n_col_blocks + i]
32704 ->solve_by_forward_substitution_matrix_valued(
32705 *(submatrices[i * n_col_blocks + j]), fixed_rank);
32706 }
32707 }
32708 }
32709 }
32710}
32711
32712
32713template <int spacedim, typename Number>
32714void
32716 const unsigned int fixed_rank)
32717{
32718 // Set OpenBLAS num threads to 1 when task parallelization is used.
32719 const int blas_num_threads = openblas_get_num_threads();
32720 openblas_set_num_threads(1);
32721
32722#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32723 Timer timer;
32724#endif
32728 this->link_hmat_nodes_on_cross_from_diagonal_blocks(this->property);
32729#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32730 timer.stop();
32731 print_wall_time(std::cout, timer, "link H-matrix nodes");
32732#endif
32733
32737 std::mutex log_stream_lock;
32738
32742 tbb::flow::graph dag;
32743
32744#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32745 timer.start();
32746#endif
32747 compute_lu_dag(dag, fixed_rank, log_stream_lock);
32748#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32749 timer.stop();
32750 print_wall_time(std::cout, timer, "compute dag");
32751#endif
32752
32753#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32754 timer.start();
32755#endif
32756 lu_assign_update_to_solve_and_factorize_dependencies();
32757#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32758 timer.stop();
32759 print_wall_time(std::cout, timer, "contribute update");
32760#endif
32761
32766 HMatrix<spacedim, Number> *top_left_node = this->get_top_left_leaf_node();
32767 Assert(top_left_node != nullptr, ExcInternalError());
32768 Assert(top_left_node->factorize_lu_or_cholesky_graph_node,
32769 ExcInternalError());
32770
32771#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32772 timer.start();
32773#endif
32774 top_left_node->factorize_lu_or_cholesky_graph_node->try_put(
32775 tbb::flow::continue_msg());
32776
32777 dag.wait_for_all();
32778#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
32779 timer.stop();
32780 print_wall_time(std::cout, timer, "compute lu");
32781#endif
32782 clear_lu_or_cholesky_task_nodes();
32783
32787 this->set_state(HMatrixSupport::lu);
32788
32789 // Restore the original OpenBLAS num threads.
32790 openblas_set_num_threads(blas_num_threads);
32791}
32792
32793
32794template <int spacedim, typename Number>
32795void
32797 const unsigned int fixed_rank,
32798 std::mutex &log_stream_lock)
32799{
32800 const unsigned int n_row_blocks = get_n_row_blocks();
32801 const unsigned int n_col_blocks = get_n_col_blocks();
32802
32807 AssertDimension(n_row_blocks, n_col_blocks);
32808
32812 for (size_type i = 0; i < n_row_blocks; i++)
32813 {
32814 // <code>i * n_col_blocks + i</code> returns the linear index for the
32815 // diagonal block on the i-th row.
32816 HMatrix<spacedim, Number> *current_diag_block =
32817 submatrices[i * n_col_blocks + i];
32818 const bool is_diag_block_leaf = current_diag_block->is_leaf();
32819
32820 current_diag_block->compute_lu_dag(dag, fixed_rank, log_stream_lock);
32821 current_diag_block->lu_factorize_diagonal_block_task(dag,
32822 log_stream_lock);
32823
32829 for (HMatrix<spacedim, Number> *current_diag_column_block =
32830 current_diag_block->next_same_level_same_column_hmat_node;
32831 current_diag_column_block != nullptr;
32832 current_diag_column_block =
32833 current_diag_column_block->next_same_level_same_column_hmat_node)
32834 {
32835 if (is_diag_block_leaf || current_diag_column_block->is_leaf())
32836 {
32842 current_diag_block->lu_solve_upper_task(
32843 dag, *current_diag_column_block, fixed_rank, log_stream_lock);
32844
32850#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
32851 std::cout << "factorize-to-solve-upper at level "
32852 << current_diag_block->bc_node->get_level() << ": ["
32853 << (*current_diag_block->row_index_range)[0] << ","
32854 << (*current_diag_block->row_index_range)[1] << "), ["
32855 << (*current_diag_block->col_index_range)[0] << ","
32856 << (*current_diag_block->col_index_range)[1]
32857 << ") --> ["
32858 << (*current_diag_column_block->row_index_range)[0]
32859 << ","
32860 << (*current_diag_column_block->row_index_range)[1]
32861 << "), ["
32862 << (*current_diag_column_block->col_index_range)[0]
32863 << ","
32864 << (*current_diag_column_block->col_index_range)[1]
32865 << ")" << std::endl;
32866#endif
32867 tbb::flow::make_edge(
32868 *(current_diag_block->factorize_lu_or_cholesky_graph_node),
32869 *(current_diag_column_block
32870 ->solve_upper_or_lower_lu_or_cholesky_graph_node));
32871 }
32872 }
32873
32879 for (HMatrix<spacedim, Number> *current_diag_row_block =
32880 current_diag_block->next_same_level_same_row_hmat_node;
32881 current_diag_row_block != nullptr;
32882 current_diag_row_block =
32883 current_diag_row_block->next_same_level_same_row_hmat_node)
32884 {
32885 if (is_diag_block_leaf || current_diag_row_block->is_leaf())
32886 {
32892 current_diag_block->lu_solve_lower_task(dag,
32893 *current_diag_row_block,
32894 fixed_rank,
32895 log_stream_lock);
32896
32902#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
32903 std::cout << "factorize-to-solve-lower at level "
32904 << current_diag_block->bc_node->get_level() << ": ["
32905 << (*current_diag_block->row_index_range)[0] << ","
32906 << (*current_diag_block->row_index_range)[1] << "), ["
32907 << (*current_diag_block->col_index_range)[0] << ","
32908 << (*current_diag_block->col_index_range)[1]
32909 << ") --> ["
32910 << (*current_diag_row_block->row_index_range)[0] << ","
32911 << (*current_diag_row_block->row_index_range)[1]
32912 << "), ["
32913 << (*current_diag_row_block->col_index_range)[0] << ","
32914 << (*current_diag_row_block->col_index_range)[1] << ")"
32915 << std::endl;
32916#endif
32917 tbb::flow::make_edge(
32918 *(current_diag_block->factorize_lu_or_cholesky_graph_node),
32919 *(current_diag_row_block
32920 ->solve_upper_or_lower_lu_or_cholesky_graph_node));
32921 }
32922 }
32923
32931 current_trailing_block =
32932 current_diag_block->next_same_level_hmat_node,
32933 *current_diag_row_block =
32934 current_diag_block->next_same_level_same_row_hmat_node,
32935 *current_diag_column_block =
32936 current_diag_block->next_same_level_same_column_hmat_node;
32937 current_trailing_block != nullptr;
32938 current_trailing_block =
32939 current_trailing_block->next_same_level_hmat_node)
32940 {
32945 if ((*current_trailing_block->row_index_range)[0] >=
32946 (*current_diag_block->row_index_range)[1] &&
32947 (*current_trailing_block->col_index_range)[0] >=
32948 (*current_diag_block->col_index_range)[1])
32949 {
32950 bool is_diag_row_block_found = false;
32951 bool is_diag_column_block_found = false;
32952
32957 while (current_diag_row_block != nullptr &&
32958 current_diag_row_block != current_diag_block)
32959 {
32960 if (*current_diag_row_block->col_index_range ==
32961 *current_trailing_block->col_index_range)
32962 {
32966 is_diag_row_block_found = true;
32967
32968 break;
32969 }
32970 else if ((*current_trailing_block->col_index_range)[0] >=
32971 (*current_diag_row_block->col_index_range)[1])
32972 {
32976 current_diag_row_block =
32977 current_diag_row_block
32978 ->next_same_level_same_row_hmat_node;
32979
32980 if (current_diag_row_block != nullptr &&
32981 (*current_diag_row_block->col_index_range)[0] >=
32982 (*current_trailing_block->col_index_range)[1])
32983 {
32990 break;
32991 }
32992 }
32993 else if ((*current_diag_row_block->col_index_range)[0] >=
32994 (*current_trailing_block->col_index_range)[1])
32995 {
32999 current_diag_row_block =
33000 current_diag_row_block
33001 ->previous_same_level_same_row_hmat_node;
33002
33003 if (current_diag_row_block != nullptr &&
33004 current_diag_row_block != current_diag_block &&
33005 (*current_trailing_block->col_index_range)[0] >=
33006 (*current_diag_row_block->col_index_range)[1])
33007 {
33014 break;
33015 }
33016 }
33017 }
33018
33019 if (is_diag_row_block_found)
33020 {
33025 while (current_diag_column_block != nullptr &&
33026 current_diag_column_block != current_diag_block)
33027 {
33028 if (*current_diag_column_block->row_index_range ==
33029 *current_trailing_block->row_index_range)
33030 {
33034 is_diag_column_block_found = true;
33035
33036 break;
33037 }
33038 else if ((*current_trailing_block->row_index_range)[0] >=
33039 (*current_diag_column_block->row_index_range)[1])
33040 {
33044 current_diag_column_block =
33045 current_diag_column_block
33046 ->next_same_level_same_column_hmat_node;
33047
33048 if (current_diag_column_block != nullptr &&
33049 (*current_diag_column_block
33050 ->row_index_range)[0] >=
33051 (*current_trailing_block->row_index_range)[1])
33052 {
33060 break;
33061 }
33062 }
33063 else if ((*current_diag_column_block
33064 ->row_index_range)[0] >=
33065 (*current_trailing_block->row_index_range)[1])
33066 {
33070 current_diag_column_block =
33071 current_diag_column_block
33072 ->previous_same_level_same_column_hmat_node;
33073
33074 if (current_diag_column_block != nullptr &&
33075 current_diag_column_block != current_diag_block &&
33076 (*current_trailing_block->row_index_range)[0] >=
33077 (*current_diag_column_block
33078 ->row_index_range)[1])
33079 {
33087 break;
33088 }
33089 }
33090 }
33091
33092 if (!is_diag_column_block_found)
33093 {
33099 if (current_diag_column_block == nullptr ||
33100 current_diag_column_block == current_diag_block)
33101 {
33102 current_diag_column_block =
33103 current_diag_block
33105 }
33106 }
33107 }
33108 else
33109 {
33115 if (current_diag_row_block == nullptr ||
33116 current_diag_row_block == current_diag_block)
33117 {
33118 current_diag_row_block =
33119 current_diag_block->next_same_level_same_row_hmat_node;
33120 }
33121 }
33122
33127 if (is_diag_row_block_found && is_diag_column_block_found)
33128 {
33129 if (current_trailing_block->is_leaf() ||
33130 current_diag_row_block->is_leaf() ||
33131 current_diag_column_block->is_leaf())
33132 {
33137 current_trailing_block->lu_update_task(
33138 dag,
33139 *current_diag_block,
33140 *current_diag_column_block,
33141 *current_diag_row_block,
33142 fixed_rank,
33143 log_stream_lock);
33144
33150 current_diag_row_block
33151 ->lu_build_solve_lower_to_update_dependencies(
33152 *current_trailing_block);
33153
33159 current_diag_column_block
33160 ->lu_or_cholesky_build_solve_upper_to_update_dependencies(
33161 *current_trailing_block);
33162 }
33163 }
33164 }
33165 }
33166 }
33167}
33168
33169
33170template <int spacedim, typename Number>
33171void
33173 tbb::flow::graph &dag,
33174 std::mutex &log_stream_lock)
33175{
33179 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
33180 ExcInvalidHMatrixBlockType(block_type));
33181
33182 this->factorize_lu_or_cholesky_graph_node = std::make_shared<TaskNode>(
33183 dag, [this, &log_stream_lock](const tbb::flow::continue_msg &msg) {
33184#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
33185 {
33186 std::lock_guard<std::mutex> lg(log_stream_lock);
33187
33188 std::cout << std::this_thread::get_id() << "#lu_factorize: ["
33189 << (*this->row_index_range)[0] << ","
33190 << (*this->row_index_range)[1] << "), ["
33191 << (*this->col_index_range)[0] << ","
33192 << (*this->col_index_range)[1] << ")" << std::endl;
33193 }
33194#endif
33195
33196 if (this->is_leaf())
33197 {
33206 Assert(this->type == FullMatrixType,
33207 ExcInvalidHMatrixType(this->type));
33208 Assert(this->fullmatrix != nullptr, ExcInternalError());
33209
33214 this->fullmatrix->compute_lu_factorization();
33215 }
33216
33217 return msg;
33218 });
33219}
33220
33221
33222template <int spacedim, typename Number>
33223void
33226 const unsigned int fixed_rank,
33227 std::mutex &log_stream_lock)
33228{
33232 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
33233 ExcInvalidHMatrixBlockType(block_type));
33234 Assert(Z.block_type != HMatrixSupport::BlockType::diagonal_block,
33235 ExcInvalidHMatrixBlockType(Z.block_type));
33236
33241 Assert(!Z.solve_upper_or_lower_lu_or_cholesky_graph_node, ExcInternalError());
33242
33243 Z.solve_upper_or_lower_lu_or_cholesky_graph_node = std::make_shared<TaskNode>(
33244 dag,
33245 [this, &Z, fixed_rank, &log_stream_lock](
33246 const tbb::flow::continue_msg &msg) {
33247#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
33248 {
33249 std::lock_guard<std::mutex> lg(log_stream_lock);
33250
33251 std::cout << std::this_thread::get_id() << "#lu_solve_upper: ["
33252 << (*Z.row_index_range)[0] << "," << (*Z.row_index_range)[1]
33253 << "), [" << (*Z.col_index_range)[0] << ","
33254 << (*Z.col_index_range)[1] << ")" << std::endl;
33255 }
33256#endif
33257
33258 this->solve_transpose_by_forward_substitution_matrix_valued(Z,
33259 fixed_rank);
33260 return msg;
33261 });
33262}
33263
33264
33265template <int spacedim, typename Number>
33266void
33269 const unsigned int fixed_rank,
33270 std::mutex &log_stream_lock)
33271{
33275 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
33276 ExcInvalidHMatrixBlockType(block_type));
33277 Assert(Z.block_type != HMatrixSupport::BlockType::diagonal_block,
33278 ExcInvalidHMatrixBlockType(Z.block_type));
33279
33284 Assert(!Z.solve_upper_or_lower_lu_or_cholesky_graph_node, ExcInternalError());
33285
33286 Z.solve_upper_or_lower_lu_or_cholesky_graph_node = std::make_shared<TaskNode>(
33287 dag,
33288 [this, &Z, fixed_rank, &log_stream_lock](
33289 const tbb::flow::continue_msg &msg) {
33290#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
33291 {
33292 std::lock_guard<std::mutex> lg(log_stream_lock);
33293
33294 std::cout << std::this_thread::get_id() << "#lu_solve_lower: ["
33295 << (*Z.row_index_range)[0] << "," << (*Z.row_index_range)[1]
33296 << "), [" << (*Z.col_index_range)[0] << ","
33297 << (*Z.col_index_range)[1] << ")" << std::endl;
33298 }
33299#endif
33300
33301 this->solve_by_forward_substitution_matrix_valued(Z, fixed_rank);
33302 return msg;
33303 });
33304}
33305
33306
33307template <int spacedim, typename Number>
33308void
33310 tbb::flow::graph &dag,
33311 HMatrix<spacedim, Number> &diag_block,
33312 HMatrix<spacedim, Number> &diag_column_block,
33313 HMatrix<spacedim, Number> &diag_row_block,
33314 const unsigned int fixed_rank,
33315 std::mutex &log_stream_lock)
33316{
33317 this->update_lu_or_cholesky_graph_nodes.push_back(
33319 &diag_block,
33320 std::make_shared<TaskNode>(
33321 dag,
33322 [this,
33323 &diag_column_block,
33324 &diag_row_block,
33325 fixed_rank,
33326 &log_stream_lock](const tbb::flow::continue_msg &msg) {
33327#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
33328 {
33329 std::lock_guard<std::mutex> lg(log_stream_lock);
33330
33331 std::cout << std::this_thread::get_id() << "#lu_update: ["
33332 << (*diag_column_block.row_index_range)[0] << ","
33333 << (*diag_column_block.row_index_range)[1] << "), ["
33334 << (*diag_column_block.col_index_range)[0] << ","
33335 << (*diag_column_block.col_index_range)[1] << ") * ["
33336 << (*diag_row_block.row_index_range)[0] << ","
33337 << (*diag_row_block.row_index_range)[1] << "), ["
33338 << (*diag_row_block.col_index_range)[0] << ","
33339 << (*diag_row_block.col_index_range)[1] << ")"
33340 << " --> [" << (*this->row_index_range)[0] << ","
33341 << (*this->row_index_range)[1] << "), ["
33342 << (*this->col_index_range)[0] << ","
33343 << (*this->col_index_range)[1] << ")" << std::endl;
33344 }
33345#endif
33346
33347 diag_column_block.mmult_level_conserving_for_parallel_lu(
33348 *this, -1.0, diag_row_block, fixed_rank);
33349
33350 return msg;
33351 })));
33352}
33353
33354
33355template <int spacedim, typename Number>
33356void
33359 HMatrix<spacedim, Number> &update_block)
33360{
33365 if (solve_upper_or_lower_lu_or_cholesky_graph_node)
33366 {
33367#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
33368 std::cout << "solve-upper-to-update at level ("
33369 << this->bc_node->get_level() << ","
33370 << update_block.bc_node->get_level() << "): ["
33371 << (*this->row_index_range)[0] << ","
33372 << (*this->row_index_range)[1] << "), ["
33373 << (*this->col_index_range)[0] << ","
33374 << (*this->col_index_range)[1] << ") --> ["
33375 << (*update_block.row_index_range)[0] << ","
33376 << (*update_block.row_index_range)[1] << "), ["
33377 << (*update_block.col_index_range)[0] << ","
33378 << (*update_block.col_index_range)[1] << ")" << std::endl;
33379#endif
33380
33381 tbb::flow::make_edge(
33382 *solve_upper_or_lower_lu_or_cholesky_graph_node,
33383 *update_block.update_lu_or_cholesky_graph_nodes.back().update);
33384 }
33385
33389 for (auto submatrix : submatrices)
33390 {
33391 submatrix->lu_or_cholesky_build_solve_upper_to_update_dependencies(
33392 update_block);
33393 }
33394}
33395
33396
33397template <int spacedim, typename Number>
33398void
33400 HMatrix<spacedim, Number> &update_block)
33401{
33406 if (solve_upper_or_lower_lu_or_cholesky_graph_node)
33407 {
33408#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
33409 std::cout << "solve-lower-to-update at level ("
33410 << this->bc_node->get_level() << ","
33411 << update_block.bc_node->get_level() << "): ["
33412 << (*this->row_index_range)[0] << ","
33413 << (*this->row_index_range)[1] << "), ["
33414 << (*this->col_index_range)[0] << ","
33415 << (*this->col_index_range)[1] << ") --> ["
33416 << (*update_block.row_index_range)[0] << ","
33417 << (*update_block.row_index_range)[1] << "), ["
33418 << (*update_block.col_index_range)[0] << ","
33419 << (*update_block.col_index_range)[1] << ")" << std::endl;
33420#endif
33421
33422 tbb::flow::make_edge(
33423 *solve_upper_or_lower_lu_or_cholesky_graph_node,
33424 *update_block.update_lu_or_cholesky_graph_nodes.back().update);
33425 }
33426
33430 for (auto submatrix : submatrices)
33431 {
33432 submatrix->lu_build_solve_lower_to_update_dependencies(update_block);
33433 }
33434}
33435
33436
33437template <int spacedim, typename Number>
33438void
33440 HMatrix<spacedim, Number> &factorize_block)
33441{
33442 for (auto &update_node : update_lu_or_cholesky_graph_nodes)
33443 {
33444#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
33445 std::cout << "update-to-factorize at level ("
33446 << this->bc_node->get_level() << ","
33447 << factorize_block.bc_node->get_level() << "): ["
33448 << (*this->row_index_range)[0] << ","
33449 << (*this->row_index_range)[1] << "), ["
33450 << (*this->col_index_range)[0] << ","
33451 << (*this->col_index_range)[1] << ") --> ["
33452 << (*factorize_block.row_index_range)[0] << ","
33453 << (*factorize_block.row_index_range)[1] << "), ["
33454 << (*factorize_block.col_index_range)[0] << ","
33455 << (*factorize_block.col_index_range)[1] << ")" << std::endl;
33456#endif
33457
33458 tbb::flow::make_edge(
33459 *update_node.update,
33460 *factorize_block.factorize_lu_or_cholesky_graph_node);
33461 }
33462
33466 for (auto submatrix : submatrices)
33467 {
33468 submatrix->lu_build_update_to_factorize_dependencies(factorize_block);
33469 }
33470}
33471
33472
33473template <int spacedim, typename Number>
33474void
33476 HMatrix<spacedim, Number> &solve_upper_or_lower_block)
33477{
33478 Assert(block_type == HMatrixSupport::BlockType::upper_triangular_block ||
33479 block_type == HMatrixSupport::BlockType::lower_triangular_block,
33480 ExcInternalError());
33481
33482 for (auto &update_node : update_lu_or_cholesky_graph_nodes)
33483 {
33484#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
33485 if (solve_upper_or_lower_block.block_type ==
33486 HMatrixSupport::BlockType::upper_triangular_block)
33487 {
33488 std::cout << "update-to-solve-lower at level ("
33489 << this->bc_node->get_level() << ","
33490 << solve_upper_or_lower_block.bc_node->get_level() << "): ["
33491 << (*update_node.diagonal_hmat_node->row_index_range)[0]
33492 << ","
33493 << (*update_node.diagonal_hmat_node->row_index_range)[1]
33494 << "), ["
33495 << (*update_node.diagonal_hmat_node->col_index_range)[0]
33496 << ","
33497 << (*update_node.diagonal_hmat_node->col_index_range)[1]
33498 << ") --> ["
33499 << (*solve_upper_or_lower_block.row_index_range)[0] << ","
33500 << (*solve_upper_or_lower_block.row_index_range)[1]
33501 << "), ["
33502 << (*solve_upper_or_lower_block.col_index_range)[0] << ","
33503 << (*solve_upper_or_lower_block.col_index_range)[1] << ")"
33504 << std::endl;
33505 }
33506 else if (solve_upper_or_lower_block.block_type ==
33507 HMatrixSupport::BlockType::lower_triangular_block)
33508 {
33509 std::cout << "update-to-solve-upper at level ("
33510 << this->bc_node->get_level() << ","
33511 << solve_upper_or_lower_block.bc_node->get_level() << "): ["
33512 << (*update_node.diagonal_hmat_node->row_index_range)[0]
33513 << ","
33514 << (*update_node.diagonal_hmat_node->row_index_range)[1]
33515 << "), ["
33516 << (*update_node.diagonal_hmat_node->col_index_range)[0]
33517 << ","
33518 << (*update_node.diagonal_hmat_node->col_index_range)[1]
33519 << ") --> ["
33520 << (*solve_upper_or_lower_block.row_index_range)[0] << ","
33521 << (*solve_upper_or_lower_block.row_index_range)[1]
33522 << "), ["
33523 << (*solve_upper_or_lower_block.col_index_range)[0] << ","
33524 << (*solve_upper_or_lower_block.col_index_range)[1] << ")"
33525 << std::endl;
33526 }
33527 else
33528 {
33529 Assert(false, ExcInternalError());
33530 }
33531#endif
33532
33533 tbb::flow::make_edge(*update_node.update,
33534 *solve_upper_or_lower_block
33536 }
33537
33541 for (auto submatrix : submatrices)
33542 {
33543 submatrix->lu_build_update_to_solve_upper_or_lower_dependencies(
33544 solve_upper_or_lower_block);
33545 }
33546}
33547
33548
33549template <int spacedim, typename Number>
33550void
33551HMatrix<spacedim,
33552 Number>::lu_assign_update_to_solve_and_factorize_dependencies()
33553{
33554 if (solve_upper_or_lower_lu_or_cholesky_graph_node)
33555 {
33560 lu_build_update_to_solve_upper_or_lower_dependencies(*this);
33561
33567 }
33568 else
33569 {
33570 if (block_type == HMatrixSupport::BlockType::diagonal_block)
33571 {
33577 if (factorize_lu_or_cholesky_graph_node)
33578 {
33579 lu_build_update_to_factorize_dependencies(*this);
33580
33587 if (parent != nullptr &&
33588 parent->factorize_lu_or_cholesky_graph_node &&
33589 // Only when the current matrix block is the last diagonal
33590 // block within its parent matrix, the
33591 // factorization-to-factorization task dependency will be
33592 // created.
33593 submatrix_index == (parent->get_n_row_blocks() - 1) *
33594 (parent->get_n_col_blocks() + 1))
33595 {
33596#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
33597 std::cout << "factorize-to-factorize at level ("
33598 << this->bc_node->get_level() << ","
33599 << parent->bc_node->get_level() << "): ["
33600 << (*this->row_index_range)[0] << ","
33601 << (*this->row_index_range)[1] << "), ["
33602 << (*this->col_index_range)[0] << ","
33603 << (*this->col_index_range)[1] << ") --> ["
33604 << (*parent->row_index_range)[0] << ","
33605 << (*parent->row_index_range)[1] << "), ["
33606 << (*parent->col_index_range)[0] << ","
33607 << (*parent->col_index_range)[1] << ")"
33608 << std::endl;
33609#endif
33610
33611 tbb::flow::make_edge(
33612 *factorize_lu_or_cholesky_graph_node,
33613 *parent->factorize_lu_or_cholesky_graph_node);
33614 }
33615 }
33616 }
33617
33623 for (auto submatrix : submatrices)
33624 {
33628 if (update_lu_or_cholesky_graph_nodes.size() > 0)
33629 {
33630 submatrix->update_lu_or_cholesky_graph_nodes.insert(
33631 submatrix->update_lu_or_cholesky_graph_nodes.end(),
33632 update_lu_or_cholesky_graph_nodes.begin(),
33633 update_lu_or_cholesky_graph_nodes.end());
33634 }
33635
33636 submatrix->lu_assign_update_to_solve_and_factorize_dependencies();
33637 }
33638 }
33639}
33640
33641
33642template <int spacedim, typename Number>
33643void
33646 const unsigned int fixed_rank) const
33647{
33648 Assert(this->state == HMatrixSupport::State::matrix,
33649 ExcInvalidHMatrixState(this->state));
33650 Assert(this->property == HMatrixSupport::Property::symmetric,
33651 ExcInvalidHMatrixProperty(this->property));
33652 Assert(this->block_type == HMatrixSupport::BlockType::diagonal_block,
33653 ExcInvalidHMatrixBlockType(this->block_type));
33654
33655 Assert(L.state == HMatrixSupport::State::matrix,
33656 ExcInvalidHMatrixState(L.state));
33657 Assert(L.property == HMatrixSupport::Property::lower_triangular ||
33658 L.property == HMatrixSupport::Property::symmetric,
33659 ExcInvalidHMatrixProperty(L.property));
33660 Assert(L.block_type == HMatrixSupport::BlockType::diagonal_block,
33661 ExcInvalidHMatrixBlockType(L.block_type));
33662
33663 if (type != HierarchicalMatrixType)
33664 {
33673 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
33674 Assert(fullmatrix != nullptr, ExcInternalError());
33675 Assert(L.fullmatrix != nullptr, ExcInternalError());
33676
33687 *(L.fullmatrix) = *fullmatrix;
33688
33689 Assert(L.fullmatrix->get_property() == LAPACKSupport::Property::symmetric,
33690 ExcInvalidLAPACKFullMatrixProperty(L.fullmatrix->get_property()));
33691
33696 L.fullmatrix->compute_cholesky_factorization();
33697 }
33698 else
33699 {
33700 const unsigned int n_row_blocks = get_n_row_blocks();
33701 const unsigned int n_col_blocks = get_n_col_blocks();
33702
33707 AssertDimension(n_row_blocks, n_col_blocks);
33708
33713 for (size_type i = 0; i < n_row_blocks; i++)
33714 {
33719 for (size_type j = 0; j <= i; j++)
33720 {
33725 HMatrix<spacedim, Number> Z(*(submatrices[i * n_col_blocks + j]));
33726
33742 for (size_type k = 0; k < j; k++)
33743 {
33744 L.submatrices[i * n_col_blocks + k]->mTmult_level_conserving(
33745 Z,
33746 -1.0,
33747 *(L.submatrices[j * n_col_blocks + k]),
33748 fixed_rank,
33749 (i == j));
33750 }
33751
33752 if (j < i)
33753 {
33760 L.submatrices[j * n_col_blocks + j]
33761 ->solve_cholesky_transpose_by_forward_substitution_matrix_valued(
33762 *(L.submatrices[i * n_col_blocks + j]), Z, fixed_rank);
33763 }
33764 else if (j == i)
33765 {
33771 *(L.submatrices[i * n_col_blocks + i]), fixed_rank);
33772 }
33773 else
33774 {
33775 Assert(false, ExcInternalError());
33776 }
33777 }
33778 }
33779 }
33780}
33781
33782
33783template <int spacedim, typename Number>
33784void
33787 const unsigned int fixed_rank)
33788{
33789 this->_compute_cholesky_factorization(L, fixed_rank);
33790
33797 L.set_state(HMatrixSupport::cholesky);
33798 this->set_state(HMatrixSupport::unusable);
33799}
33800
33801
33802template <int spacedim, typename Number>
33803void
33805 const unsigned int fixed_rank)
33806{
33807 Assert(this->state == HMatrixSupport::State::matrix,
33808 ExcInvalidHMatrixState(this->state));
33809 Assert(this->property == HMatrixSupport::Property::symmetric,
33810 ExcInvalidHMatrixProperty(this->property));
33811 Assert(this->block_type == HMatrixSupport::BlockType::diagonal_block,
33812 ExcInvalidHMatrixBlockType(this->block_type));
33813
33814 if (type != HierarchicalMatrixType)
33815 {
33824 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
33825 Assert(fullmatrix != nullptr, ExcInternalError());
33826
33827 Assert(fullmatrix->get_property() == LAPACKSupport::Property::symmetric,
33828 ExcInvalidLAPACKFullMatrixProperty(fullmatrix->get_property()));
33829
33834 fullmatrix->compute_cholesky_factorization();
33835 }
33836 else
33837 {
33838 const unsigned int n_row_blocks = get_n_row_blocks();
33839 const unsigned int n_col_blocks = get_n_col_blocks();
33840
33845 AssertDimension(n_row_blocks, n_col_blocks);
33846
33851 for (size_type i = 0; i < n_row_blocks; i++)
33852 {
33857 for (size_type j = 0; j <= i; j++)
33858 {
33874 for (size_type k = 0; k < j; k++)
33875 {
33876 submatrices[i * n_col_blocks + k]->mTmult_level_conserving(
33877 *(submatrices[i * n_col_blocks + j]),
33878 -1.0,
33879 *(submatrices[j * n_col_blocks + k]),
33880 fixed_rank,
33881 (i == j));
33882 }
33883
33884 if (j < i)
33885 {
33892 submatrices[j * n_col_blocks + j]
33893 ->solve_cholesky_transpose_by_forward_substitution_matrix_valued(
33894 *(submatrices[i * n_col_blocks + j]), fixed_rank);
33895 }
33896 else if (j == i)
33897 {
33902 submatrices[i * n_col_blocks + i]
33903 ->_compute_cholesky_factorization(fixed_rank);
33904 }
33905 else
33906 {
33907 Assert(false, ExcInternalError());
33908 }
33909 }
33910 }
33911 }
33912}
33913
33914
33915template <int spacedim, typename Number>
33916void
33918 const unsigned int fixed_rank)
33919{
33920 this->_compute_cholesky_factorization(fixed_rank);
33921
33926 this->set_state(HMatrixSupport::cholesky);
33927 this->set_property(HMatrixSupport::Property::lower_triangular);
33928}
33929
33930
33931template <int spacedim, typename Number>
33932void
33934 const unsigned int fixed_rank,
33935 std::mutex &log_stream_lock)
33936{
33937 const unsigned int n_row_blocks = get_n_row_blocks();
33938 const unsigned int n_col_blocks = get_n_col_blocks();
33939
33940 AssertDimension(n_row_blocks, n_col_blocks);
33941
33945 for (size_type i = 0; i < n_row_blocks; i++)
33946 {
33947 // <code>i * n_col_blocks + i</code> returns the linear index for the
33948 // diagonal block on the i-th row.
33949 HMatrix<spacedim, Number> *current_diag_block =
33950 submatrices[i * n_col_blocks + i];
33951 const bool is_diag_block_leaf = current_diag_block->is_leaf();
33952
33953 current_diag_block->compute_cholesky_dag(dag,
33954 fixed_rank,
33955 log_stream_lock);
33956 current_diag_block->cholesky_factorize_diagonal_block_task(
33957 dag, log_stream_lock);
33958
33964 for (HMatrix<spacedim, Number> *current_diag_column_block =
33965 current_diag_block->next_same_level_same_column_hmat_node;
33966 current_diag_column_block != nullptr;
33967 current_diag_column_block =
33968 current_diag_column_block->next_same_level_same_column_hmat_node)
33969 {
33970 if (is_diag_block_leaf || current_diag_column_block->is_leaf())
33971 {
33977 current_diag_block->cholesky_solve_upper_task(
33978 dag, *current_diag_column_block, fixed_rank, log_stream_lock);
33979
33985#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
33986 std::cout << "factorize-to-solve-transpose-upper at level "
33987 << current_diag_block->bc_node->get_level() << ": ["
33988 << (*current_diag_block->row_index_range)[0] << ","
33989 << (*current_diag_block->row_index_range)[1] << "), ["
33990 << (*current_diag_block->col_index_range)[0] << ","
33991 << (*current_diag_block->col_index_range)[1]
33992 << ") --> ["
33993 << (*current_diag_column_block->row_index_range)[0]
33994 << ","
33995 << (*current_diag_column_block->row_index_range)[1]
33996 << "), ["
33997 << (*current_diag_column_block->col_index_range)[0]
33998 << ","
33999 << (*current_diag_column_block->col_index_range)[1]
34000 << ")" << std::endl;
34001#endif
34002 tbb::flow::make_edge(
34003 *(current_diag_block->factorize_lu_or_cholesky_graph_node),
34004 *(current_diag_column_block
34005 ->solve_upper_or_lower_lu_or_cholesky_graph_node));
34006 }
34007 }
34008
34025 current_trailing_block =
34026 current_diag_block->next_same_level_hmat_node,
34027 *current_diag_column_block1 =
34028 current_diag_block->next_same_level_same_column_hmat_node,
34029 *current_diag_column_block2 =
34030 current_diag_block->next_same_level_same_column_hmat_node;
34031 current_trailing_block != nullptr;
34032 current_trailing_block =
34033 current_trailing_block->next_same_level_hmat_node)
34034 {
34039 if ((*current_trailing_block->row_index_range)[0] >=
34040 (*current_diag_block->row_index_range)[1] &&
34041 (*current_trailing_block->col_index_range)[0] >=
34042 (*current_diag_block->col_index_range)[1])
34043 {
34044 bool is_diag_column_block1_found = false;
34045 bool is_diag_column_block2_found = false;
34046
34051 while (current_diag_column_block1 != nullptr &&
34052 current_diag_column_block1 != current_diag_block)
34053 {
34054 if (*current_diag_column_block1->row_index_range ==
34055 *current_trailing_block->row_index_range)
34056 {
34060 is_diag_column_block1_found = true;
34061
34062 break;
34063 }
34064 else if ((*current_trailing_block->row_index_range)[0] >=
34065 (*current_diag_column_block1->row_index_range)[1])
34066 {
34070 current_diag_column_block1 =
34071 current_diag_column_block1
34072 ->next_same_level_same_column_hmat_node;
34073
34074 if (current_diag_column_block1 != nullptr &&
34075 (*current_diag_column_block1->row_index_range)[0] >=
34076 (*current_trailing_block->row_index_range)[1])
34077 {
34085 break;
34086 }
34087 }
34088 else if ((*current_diag_column_block1->row_index_range)[0] >=
34089 (*current_trailing_block->row_index_range)[1])
34090 {
34094 current_diag_column_block1 =
34095 current_diag_column_block1
34096 ->previous_same_level_same_column_hmat_node;
34097
34098 if (current_diag_column_block1 != nullptr &&
34099 current_diag_column_block1 != current_diag_block &&
34100 (*current_trailing_block->row_index_range)[0] >=
34101 (*current_diag_column_block1->row_index_range)[1])
34102 {
34110 break;
34111 }
34112 }
34113 }
34114
34115 if (is_diag_column_block1_found)
34116 {
34122 while (current_diag_column_block2 != nullptr &&
34123 current_diag_column_block2 != current_diag_block)
34124 {
34125 if (*current_diag_column_block2->row_index_range ==
34126 *current_trailing_block->col_index_range)
34127 {
34131 is_diag_column_block2_found = true;
34132
34133 break;
34134 }
34135 else if ((*current_trailing_block->col_index_range)[0] >=
34136 (*current_diag_column_block2
34137 ->row_index_range)[1])
34138 {
34142 current_diag_column_block2 =
34143 current_diag_column_block2
34144 ->next_same_level_same_column_hmat_node;
34145
34146 if (current_diag_column_block2 != nullptr &&
34147 (*current_diag_column_block2
34148 ->row_index_range)[0] >=
34149 (*current_trailing_block->col_index_range)[1])
34150 {
34158 break;
34159 }
34160 }
34161 else if ((*current_diag_column_block2
34162 ->row_index_range)[0] >=
34163 (*current_trailing_block->col_index_range)[1])
34164 {
34168 current_diag_column_block2 =
34169 current_diag_column_block2
34170 ->previous_same_level_same_column_hmat_node;
34171
34172 if (current_diag_column_block2 != nullptr &&
34173 current_diag_column_block2 !=
34174 current_diag_block &&
34175 (*current_trailing_block->col_index_range)[0] >=
34176 (*current_diag_column_block2
34177 ->row_index_range)[1])
34178 {
34186 break;
34187 }
34188 }
34189 }
34190
34191 if (!is_diag_column_block2_found)
34192 {
34198 if (current_diag_column_block2 == nullptr ||
34199 current_diag_column_block2 == current_diag_block)
34200 {
34201 current_diag_column_block2 =
34202 current_diag_block
34204 }
34205 }
34206 }
34207 else
34208 {
34214 if (current_diag_column_block1 == nullptr ||
34215 current_diag_column_block1 == current_diag_block)
34216 {
34217 current_diag_column_block1 =
34218 current_diag_block
34220 }
34221 }
34222
34228 if (is_diag_column_block1_found && is_diag_column_block2_found)
34229 {
34230 if (current_trailing_block->is_leaf() ||
34231 current_diag_column_block1->is_leaf() ||
34232 current_diag_column_block2->is_leaf())
34233 {
34238 current_trailing_block->cholesky_update_task(
34239 dag,
34240 *current_diag_block,
34241 *current_diag_column_block1,
34242 *current_diag_column_block2,
34243 fixed_rank,
34244 log_stream_lock);
34245
34251 current_diag_column_block1
34252 ->lu_or_cholesky_build_solve_upper_to_update_dependencies(
34253 *current_trailing_block);
34254
34260 current_diag_column_block2
34261 ->lu_or_cholesky_build_solve_upper_to_update_dependencies(
34262 *current_trailing_block);
34263 }
34264 }
34265 }
34266 }
34267 }
34268}
34269
34270
34271template <int spacedim, typename Number>
34272void
34274 tbb::flow::graph &dag,
34275 std::mutex &log_stream_lock)
34276{
34280 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
34281 ExcInvalidHMatrixBlockType(block_type));
34282
34283 this->factorize_lu_or_cholesky_graph_node = std::make_shared<TaskNode>(
34284 dag, [this, &log_stream_lock](const tbb::flow::continue_msg &msg) {
34285#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
34286 {
34287 std::lock_guard<std::mutex> lg(log_stream_lock);
34288
34289 std::cout << std::this_thread::get_id() << "#cholesky_factorize: ["
34290 << (*this->row_index_range)[0] << ","
34291 << (*this->row_index_range)[1] << "), ["
34292 << (*this->col_index_range)[0] << ","
34293 << (*this->col_index_range)[1] << ")" << std::endl;
34294 }
34295#endif
34296
34297 if (this->is_leaf())
34298 {
34304 Assert(this->type == FullMatrixType,
34305 ExcInvalidHMatrixType(this->type));
34306 Assert(this->fullmatrix != nullptr, ExcInternalError());
34307 Assert(this->fullmatrix->get_property() ==
34308 LAPACKSupport::Property::symmetric,
34309 ExcInvalidLAPACKFullMatrixProperty(
34310 fullmatrix->get_property()));
34311
34316 this->fullmatrix->compute_cholesky_factorization();
34317 }
34318
34319 return msg;
34320 });
34321}
34322
34323
34324template <int spacedim, typename Number>
34325void
34327 tbb::flow::graph &dag,
34329 const unsigned int fixed_rank,
34330 std::mutex &log_stream_lock)
34331{
34335 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
34336 ExcInvalidHMatrixBlockType(block_type));
34337 Assert(Z.block_type != HMatrixSupport::BlockType::diagonal_block,
34338 ExcInvalidHMatrixBlockType(Z.block_type));
34339
34344 Assert(!Z.solve_upper_or_lower_lu_or_cholesky_graph_node, ExcInternalError());
34345
34346 Z.solve_upper_or_lower_lu_or_cholesky_graph_node = std::make_shared<TaskNode>(
34347 dag,
34348 [this, &Z, fixed_rank, &log_stream_lock](
34349 const tbb::flow::continue_msg &msg) {
34350#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
34351 {
34352 std::lock_guard<std::mutex> lg(log_stream_lock);
34353
34354 std::cout << std::this_thread::get_id() << "#cholesky_solve_upper: ["
34355 << (*Z.row_index_range)[0] << "," << (*Z.row_index_range)[1]
34356 << "), [" << (*Z.col_index_range)[0] << ","
34357 << (*Z.col_index_range)[1] << ")" << std::endl;
34358 }
34359#endif
34360
34361 this->solve_cholesky_transpose_by_forward_substitution_matrix_valued(
34362 Z, fixed_rank);
34363 return msg;
34364 });
34365}
34366
34367
34368template <int spacedim, typename Number>
34369void
34371 tbb::flow::graph &dag,
34372 HMatrix<spacedim, Number> &diag_block,
34373 HMatrix<spacedim, Number> &diag_column_block1,
34374 HMatrix<spacedim, Number> &diag_column_block2,
34375 const unsigned int fixed_rank,
34376 std::mutex &log_stream_lock)
34377{
34378 this->update_lu_or_cholesky_graph_nodes.push_back(
34380 &diag_block,
34381 std::make_shared<TaskNode>(
34382 dag,
34383 [this,
34384 &diag_column_block1,
34385 &diag_column_block2,
34386 fixed_rank,
34387 &log_stream_lock](const tbb::flow::continue_msg &msg) {
34388#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 3
34389 {
34390 std::lock_guard<std::mutex> lg(log_stream_lock);
34391
34392 std::cout << std::this_thread::get_id() << "#cholesky_update: ["
34393 << (*diag_column_block1.row_index_range)[0] << ","
34394 << (*diag_column_block1.row_index_range)[1] << "), ["
34395 << (*diag_column_block1.col_index_range)[0] << ","
34396 << (*diag_column_block1.col_index_range)[1] << ") * ["
34397 << (*diag_column_block2.row_index_range)[0] << ","
34398 << (*diag_column_block2.row_index_range)[1] << "), ["
34399 << (*diag_column_block2.col_index_range)[0] << ","
34400 << (*diag_column_block2.col_index_range)[1] << ")^T"
34401 << " --> [" << (*this->row_index_range)[0] << ","
34402 << (*this->row_index_range)[1] << "), ["
34403 << (*this->col_index_range)[0] << ","
34404 << (*this->col_index_range)[1] << ")" << std::endl;
34405 }
34406#endif
34407
34408 diag_column_block1.mTmult_level_conserving_for_parallel_cholesky(
34409 *this,
34410 -1.0,
34411 diag_column_block2,
34412 fixed_rank,
34413 this->property == HMatrixSupport::Property::symmetric);
34414
34415 return msg;
34416 })));
34417}
34418
34419
34420template <int spacedim, typename Number>
34421void
34423 HMatrix<spacedim, Number> &factorize_block)
34424{
34425 for (auto &update_node : update_lu_or_cholesky_graph_nodes)
34426 {
34427#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
34428 std::cout << "update-to-factorize at level ("
34429 << this->bc_node->get_level() << ","
34430 << factorize_block.bc_node->get_level() << "): ["
34431 << (*this->row_index_range)[0] << ","
34432 << (*this->row_index_range)[1] << "), ["
34433 << (*this->col_index_range)[0] << ","
34434 << (*this->col_index_range)[1] << ") --> ["
34435 << (*factorize_block.row_index_range)[0] << ","
34436 << (*factorize_block.row_index_range)[1] << "), ["
34437 << (*factorize_block.col_index_range)[0] << ","
34438 << (*factorize_block.col_index_range)[1] << ")" << std::endl;
34439#endif
34440
34441 tbb::flow::make_edge(
34442 *update_node.update,
34443 *factorize_block.factorize_lu_or_cholesky_graph_node);
34444 }
34445
34449 for (auto submatrix : submatrices)
34450 {
34451 if (submatrix->block_type !=
34452 HMatrixSupport::BlockType::upper_triangular_block)
34453 {
34454 submatrix->cholesky_build_update_to_factorize_dependencies(
34455 factorize_block);
34456 }
34457 }
34458}
34459
34460
34461template <int spacedim, typename Number>
34462void
34464 HMatrix<spacedim, Number> &solve_upper_block)
34465{
34466 Assert(block_type == HMatrixSupport::BlockType::lower_triangular_block,
34467 ExcInternalError());
34468
34469 for (auto &update_node : update_lu_or_cholesky_graph_nodes)
34470 {
34471#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
34472 Assert(solve_upper_block.block_type ==
34473 HMatrixSupport::BlockType::lower_triangular_block,
34474 ExcInvalidHMatrixBlockType(solve_upper_block.block_type));
34475
34476 std::cout << "update-to-solve-upper at level ("
34477 << this->bc_node->get_level() << ","
34478 << solve_upper_block.bc_node->get_level() << "): ["
34479 << (*update_node.diagonal_hmat_node->row_index_range)[0] << ","
34480 << (*update_node.diagonal_hmat_node->row_index_range)[1]
34481 << "), ["
34482 << (*update_node.diagonal_hmat_node->col_index_range)[0] << ","
34483 << (*update_node.diagonal_hmat_node->col_index_range)[1]
34484 << ") --> [" << (*solve_upper_block.row_index_range)[0] << ","
34485 << (*solve_upper_block.row_index_range)[1] << "), ["
34486 << (*solve_upper_block.col_index_range)[0] << ","
34487 << (*solve_upper_block.col_index_range)[1] << ")" << std::endl;
34488#endif
34489
34490 tbb::flow::make_edge(
34491 *update_node.update,
34493 }
34494
34498 for (auto submatrix : submatrices)
34499 {
34500 if (submatrix->block_type !=
34501 HMatrixSupport::BlockType::upper_triangular_block)
34502 {
34503 submatrix->cholesky_build_update_to_solve_upper_dependencies(
34504 solve_upper_block);
34505 }
34506 }
34507}
34508
34509
34510template <int spacedim, typename Number>
34511void
34512HMatrix<spacedim,
34513 Number>::cholesky_assign_update_to_solve_and_factorize_dependencies()
34514{
34515 if (solve_upper_or_lower_lu_or_cholesky_graph_node)
34516 {
34521 cholesky_build_update_to_solve_upper_dependencies(*this);
34522
34528 }
34529 else
34530 {
34531 if (block_type == HMatrixSupport::BlockType::diagonal_block)
34532 {
34538 if (factorize_lu_or_cholesky_graph_node)
34539 {
34540 cholesky_build_update_to_factorize_dependencies(*this);
34541
34548 if (parent != nullptr &&
34549 parent->factorize_lu_or_cholesky_graph_node &&
34550 // Only when the current matrix block is the last diagonal
34551 // block within its parent matrix, the
34552 // factorization-to-factorization task dependency will be
34553 // created.
34554 submatrix_index == (parent->get_n_row_blocks() - 1) *
34555 (parent->get_n_col_blocks() + 1))
34556 {
34557#if ENABLE_DEBUG == 1 && MESSAGE_LEVEL >= 2
34558 std::cout << "factorize-to-factorize at level ("
34559 << this->bc_node->get_level() << ","
34560 << parent->bc_node->get_level() << "): ["
34561 << (*this->row_index_range)[0] << ","
34562 << (*this->row_index_range)[1] << "), ["
34563 << (*this->col_index_range)[0] << ","
34564 << (*this->col_index_range)[1] << ") --> ["
34565 << (*parent->row_index_range)[0] << ","
34566 << (*parent->row_index_range)[1] << "), ["
34567 << (*parent->col_index_range)[0] << ","
34568 << (*parent->col_index_range)[1] << ")"
34569 << std::endl;
34570#endif
34571
34572 tbb::flow::make_edge(
34573 *factorize_lu_or_cholesky_graph_node,
34574 *parent->factorize_lu_or_cholesky_graph_node);
34575 }
34576 }
34577 }
34578
34584 for (auto submatrix : submatrices)
34585 {
34586 if (submatrix->block_type !=
34587 HMatrixSupport::BlockType::upper_triangular_block)
34588 {
34592 if (update_lu_or_cholesky_graph_nodes.size() > 0)
34593 {
34594 submatrix->update_lu_or_cholesky_graph_nodes.insert(
34595 submatrix->update_lu_or_cholesky_graph_nodes.end(),
34596 update_lu_or_cholesky_graph_nodes.begin(),
34597 update_lu_or_cholesky_graph_nodes.end());
34598 }
34599
34600 submatrix
34601 ->cholesky_assign_update_to_solve_and_factorize_dependencies();
34602 }
34603 }
34604 }
34605}
34606
34607
34608template <int spacedim, typename Number>
34609double
34611 const HMatrixSupport::Property top_hmat_property) const
34612{
34613 Assert(type == HMatrixType::FullMatrixType, ExcInvalidHMatrixType(type));
34614 Assert(fullmatrix != nullptr, ExcInternalError());
34615
34616 switch (top_hmat_property)
34617 {
34618 case HMatrixSupport::Property::general: {
34619 return m * n;
34620 }
34621 case HMatrixSupport::Property::symmetric:
34622 case HMatrixSupport::Property::hermite_symmetric: {
34623 switch (block_type)
34624 {
34625 case HMatrixSupport::BlockType::diagonal_block: {
34626 return m * n;
34627 }
34628 case HMatrixSupport::BlockType::lower_triangular_block: {
34629 return 2 * m * n;
34630 }
34631 default: {
34632 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34633
34634 return 0;
34635 }
34636 }
34637 }
34638 case HMatrixSupport::Property::lower_triangular: {
34639 switch (block_type)
34640 {
34641 case HMatrixSupport::BlockType::diagonal_block: {
34642 return m * n / 2.0;
34643 }
34644 case HMatrixSupport::BlockType::lower_triangular_block: {
34645 return m * n;
34646 }
34647 default: {
34648 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34649
34650 return 0;
34651 }
34652 }
34653 }
34654 case HMatrixSupport::Property::upper_triangular: {
34655 switch (block_type)
34656 {
34657 case HMatrixSupport::BlockType::diagonal_block: {
34658 return m * n / 2.0;
34659 }
34660 case HMatrixSupport::BlockType::upper_triangular_block: {
34661 return m * n;
34662 }
34663 default: {
34664 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34665
34666 return 0;
34667 }
34668 }
34669 }
34670 default: {
34671 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
34672
34673 return 0;
34674 }
34675 }
34676}
34677
34678
34679template <int spacedim, typename Number>
34680double
34682 const HMatrixSupport::Property top_hmat_property) const
34683{
34684 Assert(type == HMatrixType::RkMatrixType, ExcInvalidHMatrixType(type));
34685 Assert(rkmatrix != nullptr, ExcInternalError());
34686
34687 switch (top_hmat_property)
34688 {
34689 case HMatrixSupport::Property::general: {
34690 return rkmatrix->get_formal_rank() * (m + n);
34691 }
34692 case HMatrixSupport::Property::symmetric:
34693 case HMatrixSupport::Property::hermite_symmetric: {
34694 if (block_type == HMatrixSupport::BlockType::lower_triangular_block)
34695 {
34696 return 2 * rkmatrix->get_formal_rank() * (m + n);
34697 }
34698 else
34699 {
34700 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34701
34702 return 0;
34703 }
34704 }
34705 case HMatrixSupport::Property::lower_triangular: {
34706 if (block_type == HMatrixSupport::BlockType::lower_triangular_block)
34707 {
34708 return rkmatrix->get_formal_rank() * (m + n);
34709 }
34710 else
34711 {
34712 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34713
34714 return 0;
34715 }
34716 }
34717 case HMatrixSupport::Property::upper_triangular: {
34718 if (block_type == HMatrixSupport::BlockType::upper_triangular_block)
34719 {
34720 return rkmatrix->get_formal_rank() * (m + n);
34721 }
34722 else
34723 {
34724 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34725
34726 return 0;
34727 }
34728 }
34729 default: {
34730 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
34731
34732 return 0;
34733 }
34734 }
34735}
34736
34737
34738template <int spacedim, typename Number>
34739void
34741 std::vector<double> &task_costs) const
34742{
34743 AssertDimension(leaf_set.size(), task_costs.size());
34744
34745 unsigned int i = 0;
34746 for (const auto hmat : leaf_set)
34747 {
34748 switch (hmat->type)
34749 {
34751 task_costs[i] =
34752 hmat->compute_near_field_hmat_vmult_or_Tvmult_task_cost(
34753 property);
34754
34755 break;
34756 }
34758 task_costs[i] =
34759 hmat->compute_far_field_hmat_vmult_or_Tvmult_task_cost(
34760 property);
34761
34762 break;
34763 }
34764 default: {
34765 Assert(false, ExcInvalidHMatrixType(hmat->type));
34766 task_costs[i] = 0;
34767
34768 break;
34769 }
34770 }
34771
34772 i++;
34773 }
34774}
34775
34776
34777template <int spacedim, typename Number>
34778double
34780 const HMatrixSupport::Property top_hmat_property) const
34781{
34782 Assert(type == HMatrixType::FullMatrixType, ExcInvalidHMatrixType(type));
34783 Assert(fullmatrix != nullptr, ExcInternalError());
34784
34785 switch (top_hmat_property)
34786 {
34787 case HMatrixSupport::Property::general: {
34788 return m * n;
34789 }
34790 case HMatrixSupport::Property::symmetric:
34791 case HMatrixSupport::Property::hermite_symmetric:
34792 case HMatrixSupport::Property::lower_triangular: {
34793 switch (block_type)
34794 {
34795 case HMatrixSupport::BlockType::diagonal_block: {
34796 return m * n / 2.0 + m / 2.0;
34797 }
34798 case HMatrixSupport::BlockType::lower_triangular_block: {
34799 return m * n;
34800 }
34801 default: {
34802 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34803
34804 return 0;
34805 }
34806 }
34807 }
34808 case HMatrixSupport::Property::upper_triangular: {
34809 switch (block_type)
34810 {
34811 case HMatrixSupport::BlockType::diagonal_block: {
34812 return m * n / 2.0 + m / 2.0;
34813 }
34814 case HMatrixSupport::BlockType::upper_triangular_block: {
34815 return m * n;
34816 }
34817 default: {
34818 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34819
34820 return 0;
34821 }
34822 }
34823 }
34824 default: {
34825 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
34826
34827 return 0;
34828 }
34829 }
34830}
34831
34832
34833template <int spacedim, typename Number>
34834void
34836 std::vector<double> &task_costs) const
34837{
34838 AssertDimension(near_field_leaf_set.size(), task_costs.size());
34839
34840 unsigned int i = 0;
34841 for (const auto hmat : near_field_leaf_set)
34842 {
34843 Assert(hmat->type == HMatrixType::FullMatrixType,
34844 ExcInvalidHMatrixType(hmat->type));
34845 task_costs[i] =
34846 hmat->compute_near_field_hmat_assembly_task_cost(property);
34847
34848 i++;
34849 }
34850}
34851
34852
34853template <int spacedim, typename Number>
34854double
34856 const HMatrixSupport::Property top_hmat_property) const
34857{
34858 Assert(type == HMatrixType::RkMatrixType, ExcInvalidHMatrixType(type));
34859 Assert(rkmatrix != nullptr, ExcInternalError());
34860
34865 switch (top_hmat_property)
34866 {
34867 case HMatrixSupport::Property::general: {
34868 if (block_type == HMatrixSupport::BlockType::lower_triangular_block ||
34869 block_type == HMatrixSupport::BlockType::upper_triangular_block)
34870 {
34871 return rkmatrix->get_formal_rank() * (m + n);
34872 }
34873 else
34874 {
34875 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34876
34877 return 0;
34878 }
34879 }
34880 case HMatrixSupport::Property::symmetric:
34881 case HMatrixSupport::Property::hermite_symmetric:
34882 case HMatrixSupport::Property::lower_triangular: {
34883 if (block_type == HMatrixSupport::BlockType::lower_triangular_block)
34884 {
34885 return rkmatrix->get_formal_rank() * (m + n);
34886 }
34887 else
34888 {
34889 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34890
34891 return 0;
34892 }
34893 }
34894 case HMatrixSupport::Property::upper_triangular: {
34895 if (block_type == HMatrixSupport::BlockType::upper_triangular_block)
34896 {
34897 return rkmatrix->get_formal_rank() * (m + n);
34898 }
34899 else
34900 {
34901 Assert(false, ExcInvalidHMatrixBlockType(block_type));
34902
34903 return 0;
34904 }
34905 }
34906 default: {
34907 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
34908
34909 return 0;
34910 }
34911 }
34912}
34913
34914
34915template <int spacedim, typename Number>
34916void
34918 std::vector<double> &task_costs) const
34919{
34920 AssertDimension(far_field_leaf_set.size(), task_costs.size());
34921
34922 unsigned int i = 0;
34923 for (const auto hmat : far_field_leaf_set)
34924 {
34925 Assert(hmat->type == HMatrixType::RkMatrixType,
34926 ExcInvalidHMatrixType(hmat->type));
34927 task_costs[i] = hmat->compute_far_field_hmat_assembly_task_cost(property);
34928
34929 i++;
34930 }
34931}
34932
34933
34934template <int spacedim, typename Number>
34935void
34937 const std::pair<int64_t, int64_t> &interval,
34938 const unsigned int thread_no)
34939{
34940 Assert(interval.second >= interval.first, ExcInternalError());
34941
34942 const unsigned int hmat_num = interval.second - interval.first + 1;
34943 std::vector<types::global_dof_index> index_range_lower_bound(hmat_num);
34944 std::vector<types::global_dof_index> index_range_upper_bound(hmat_num);
34945
34946 for (unsigned int i = interval.first; i <= interval.second; i++)
34947 {
34948 index_range_lower_bound[i - interval.first] =
34949 (*leaf_set[i]->row_index_range)[0];
34950 index_range_upper_bound[i - interval.first] =
34951 (*leaf_set[i]->row_index_range)[1];
34952 }
34953
34958 typename std::vector<types::global_dof_index>::iterator min_it =
34959 std::min_element(index_range_lower_bound.begin(),
34960 index_range_lower_bound.end());
34961 typename std::vector<types::global_dof_index>::iterator max_it =
34962 std::max_element(index_range_upper_bound.begin(),
34963 index_range_upper_bound.end());
34964
34965 (*data_for_vmult_or_tvmult_threads)[thread_no]
34966 .local_vmult_result_index_range[0] = *min_it;
34967 (*data_for_vmult_or_tvmult_threads)[thread_no]
34968 .local_vmult_result_index_range[1] = *max_it;
34969
34970 Assert((*data_for_vmult_or_tvmult_threads)[thread_no]
34971 .local_vmult_result_index_range[1] >
34972 (*data_for_vmult_or_tvmult_threads)[thread_no]
34973 .local_vmult_result_index_range[0],
34974 ExcInternalError());
34975}
34976
34977
34978template <int spacedim, typename Number>
34979void
34981 const std::pair<int64_t, int64_t> &interval,
34982 const unsigned int thread_no)
34983{
34984 Assert(interval.second >= interval.first, ExcInternalError());
34985
34986 const unsigned int hmat_num = interval.second - interval.first + 1;
34987 std::vector<types::global_dof_index> index_range_lower_bound(hmat_num);
34988 std::vector<types::global_dof_index> index_range_upper_bound(hmat_num);
34989
34990 for (unsigned int i = interval.first; i <= interval.second; i++)
34991 {
34992 index_range_lower_bound[i - interval.first] =
34993 (*leaf_set[i]->col_index_range)[0];
34994 index_range_upper_bound[i - interval.first] =
34995 (*leaf_set[i]->col_index_range)[1];
34996 }
34997
35002 typename std::vector<types::global_dof_index>::iterator min_it =
35003 std::min_element(index_range_lower_bound.begin(),
35004 index_range_lower_bound.end());
35005 typename std::vector<types::global_dof_index>::iterator max_it =
35006 std::max_element(index_range_upper_bound.begin(),
35007 index_range_upper_bound.end());
35008
35009 (*data_for_vmult_or_tvmult_threads)[thread_no]
35010 .local_tvmult_result_index_range[0] = *min_it;
35011 (*data_for_vmult_or_tvmult_threads)[thread_no]
35012 .local_tvmult_result_index_range[1] = *max_it;
35013
35014 Assert((*data_for_vmult_or_tvmult_threads)[thread_no]
35015 .local_tvmult_result_index_range[1] >
35016 (*data_for_vmult_or_tvmult_threads)[thread_no]
35017 .local_tvmult_result_index_range[0],
35018 ExcInternalError());
35019}
35020
35021
35022template <int spacedim, typename Number>
35023void
35026 const unsigned int thread_no)
35027{
35028 const unsigned int thread_num = data_for_vmult_or_tvmult_threads->size();
35029
35030 (*data_for_vmult_or_tvmult_threads)[thread_no]
35031 .vmult_result_index_ranges_contributed_from_other_threads.clear();
35032 (*data_for_vmult_or_tvmult_threads)[thread_no]
35033 .vmult_result_index_ranges_contributed_from_other_threads.resize(
35034 thread_num);
35035
35036 std::array<types::global_dof_index, 2> range_intersection;
35037
35038 for (unsigned int i = 0; i < thread_num; i++)
35039 {
35040 intersect(
35041 (*data_for_vmult_or_tvmult_threads)[thread_no].vmult_result_index_range,
35042 (*data_for_vmult_or_tvmult_threads)[i].local_vmult_result_index_range,
35043 range_intersection);
35044
35045 (*data_for_vmult_or_tvmult_threads)[thread_no]
35046 .vmult_result_index_ranges_contributed_from_other_threads[i] =
35047 range_intersection;
35048 }
35049}
35050
35051
35052template <int spacedim, typename Number>
35053void
35056 const unsigned int thread_no)
35057{
35058 const unsigned int thread_num = data_for_vmult_or_tvmult_threads->size();
35059
35060 (*data_for_vmult_or_tvmult_threads)[thread_no]
35061 .tvmult_result_index_ranges_contributed_from_other_threads.clear();
35062 (*data_for_vmult_or_tvmult_threads)[thread_no]
35063 .tvmult_result_index_ranges_contributed_from_other_threads.resize(
35064 thread_num);
35065
35066 std::array<types::global_dof_index, 2> range_intersection;
35067
35068 for (unsigned int i = 0; i < thread_num; i++)
35069 {
35070 intersect(
35071 (*data_for_vmult_or_tvmult_threads)[thread_no]
35072 .tvmult_result_index_range,
35073 (*data_for_vmult_or_tvmult_threads)[i].local_tvmult_result_index_range,
35074 range_intersection);
35075
35076 (*data_for_vmult_or_tvmult_threads)[thread_no]
35077 .tvmult_result_index_ranges_contributed_from_other_threads[i] =
35078 range_intersection;
35079 }
35080}
35081
35082
35083template <int spacedim, typename Number>
35084unsigned int
35086 const bool is_vmult,
35087 const bool is_tvmult) const
35088{
35093 unsigned int thread_num =
35094 std::min(static_cast<size_t>(MultithreadInfo::n_threads()),
35095 leaf_set.size());
35096
35102 if (is_vmult)
35103 {
35104 if (this->m < thread_num)
35105 {
35106 thread_num = this->m;
35107 }
35108 }
35109
35115 if (is_tvmult)
35116 {
35117 if (this->n < thread_num)
35118 {
35119 thread_num = this->n;
35120 }
35121 }
35122
35123 return thread_num;
35124}
35125
35126
35127template <int spacedim, typename Number>
35128void
35130 const bool is_tvmult)
35131{
35135 Assert(parent == nullptr, ExcInternalError());
35136
35137 const unsigned int thread_num =
35138 compute_vmult_or_tvmult_thread_num(is_vmult, is_tvmult);
35139
35144 if (thread_num > 1)
35145 {
35146 data_for_vmult_or_tvmult_threads =
35147 std::make_unique<std::vector<VmultOrTvmultThreadData>>(thread_num);
35148
35152 std::vector<double> task_costs(leaf_set.size());
35153 this->compute_leaf_set_vmult_or_Tvmult_task_costs(task_costs);
35154
35158 auto cost_func = [&task_costs](int i, int j) -> double {
35159 double sum = 0.0;
35160
35161 for (int k = i; k <= j; k++)
35162 {
35163 sum += task_costs[k];
35164 }
35165
35166 return sum;
35167 };
35168
35169 SequencePartitioner<decltype(cost_func)> sp(task_costs.size(),
35170 thread_num,
35171 cost_func);
35172 sp.partition();
35173
35174 std::vector<std::pair<int64_t, int64_t>> leaf_set_intervals;
35175 sp.get_partitions(leaf_set_intervals);
35176
35177 auto prepare_thread_self_data =
35178 [this,
35179 thread_num,
35180 is_vmult,
35181 is_tvmult](const std::pair<int64_t, int64_t> &interval,
35182 const unsigned int thread_no) -> void {
35183 (*this->data_for_vmult_or_tvmult_threads)[thread_no].leaf_set_interval =
35184 interval;
35185
35186 if (is_vmult)
35187 {
35191 this->get_row_index_range_for_leaf_set_interval(interval,
35192 thread_no);
35193
35197 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35198 .local_vmult_result.reinit(
35199 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35200 .local_vmult_result_index_range[1] -
35201 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35202 .local_vmult_result_index_range[0]);
35203
35208 types::global_dof_index vmult_result_vector_size =
35209 this->m / thread_num;
35210 Assert(vmult_result_vector_size > 0, ExcInternalError());
35211
35212 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35213 .vmult_result_index_range[0] =
35214 thread_no * vmult_result_vector_size;
35215 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35216 .vmult_result_index_range[1] =
35217 thread_no == thread_num - 1 ?
35218 m :
35219 (thread_no + 1) * vmult_result_vector_size;
35220 }
35221
35222 if (is_tvmult)
35223 {
35227 this->get_column_index_range_for_leaf_set_interval(interval,
35228 thread_no);
35229
35233 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35234 .local_tvmult_result.reinit(
35235 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35236 .local_tvmult_result_index_range[1] -
35237 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35238 .local_tvmult_result_index_range[0]);
35239
35244 types::global_dof_index tvmult_result_vector_size =
35245 this->n / thread_num;
35246 Assert(tvmult_result_vector_size > 0, ExcInternalError());
35247
35248 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35249 .tvmult_result_index_range[0] =
35250 thread_no * tvmult_result_vector_size;
35251 (*this->data_for_vmult_or_tvmult_threads)[thread_no]
35252 .tvmult_result_index_range[1] =
35253 thread_no == thread_num - 1 ?
35254 n :
35255 (thread_no + 1) * tvmult_result_vector_size;
35256 }
35257 };
35258
35259 Threads::TaskGroup<void> thread_self_preparation_tasks;
35260 for (unsigned int i = 0; i < thread_num; i++)
35261 {
35262 thread_self_preparation_tasks += Threads::new_task(
35263 std::bind(prepare_thread_self_data, leaf_set_intervals[i], i));
35264 }
35265
35266 thread_self_preparation_tasks.join_all();
35267
35268 auto prepare_thread_mutual_data =
35269 [this, is_vmult, is_tvmult](const unsigned int thread_no) -> void {
35270 if (is_vmult)
35271 {
35276 this->compute_vmult_contributing_index_ranges_from_all_threads(
35277 thread_no);
35278 }
35279
35280 if (is_tvmult)
35281 {
35286 this->compute_tvmult_contributing_index_ranges_from_all_threads(
35287 thread_no);
35288 }
35289 };
35290
35291 Threads::TaskGroup<void> thread_mutual_preparation_tasks;
35292 for (unsigned int i = 0; i < thread_num; i++)
35293 {
35294 thread_mutual_preparation_tasks +=
35295 Threads::new_task(std::bind(prepare_thread_mutual_data, i));
35296 }
35297
35298 thread_mutual_preparation_tasks.join_all();
35299 }
35300 else
35301 {
35302 // Fallback to the serial recursive mode.
35303 this->set_vmult_strategy(
35305 }
35306}
35307
35308
35309template <int spacedim, typename Number>
35310void
35312 const unsigned int fixed_rank)
35313{
35314 // Set OpenBLAS num threads to 1 when task parallelization is used.
35315 const int blas_num_threads = openblas_get_num_threads();
35316 openblas_set_num_threads(1);
35317
35318#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35319 Timer timer;
35320#endif
35324 this->link_hmat_nodes_on_cross_from_diagonal_blocks(this->property);
35325#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35326 timer.stop();
35327 print_wall_time(std::cout, timer, "link H-matrix nodes");
35328#endif
35329
35333 std::mutex log_stream_lock;
35334
35338 tbb::flow::graph dag;
35339
35340#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35341 timer.start();
35342#endif
35343 compute_cholesky_dag(dag, fixed_rank, log_stream_lock);
35344#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35345 timer.stop();
35346 print_wall_time(std::cout, timer, "compute dag");
35347#endif
35348
35349#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35350 timer.start();
35351#endif
35352 cholesky_assign_update_to_solve_and_factorize_dependencies();
35353#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35354 timer.stop();
35355 print_wall_time(std::cout, timer, "contribute update");
35356#endif
35357
35362 HMatrix<spacedim, Number> *top_left_node = this->get_top_left_leaf_node();
35363 Assert(top_left_node != nullptr, ExcInternalError());
35364 Assert(top_left_node->factorize_lu_or_cholesky_graph_node,
35365 ExcInternalError());
35366
35367#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35368 timer.start();
35369#endif
35370 top_left_node->factorize_lu_or_cholesky_graph_node->try_put(
35371 tbb::flow::continue_msg());
35372
35373 dag.wait_for_all();
35374#if ENABLE_DEBUG == 1 && ENABLE_TIMER == 1
35375 timer.stop();
35376 print_wall_time(std::cout, timer, "compute cholesky");
35377#endif
35378 clear_lu_or_cholesky_task_nodes();
35379
35384 this->set_state(HMatrixSupport::cholesky);
35385 this->set_property(HMatrixSupport::Property::lower_triangular);
35386
35387 // Restore the original OpenBLAS num threads.
35388 openblas_set_num_threads(blas_num_threads);
35389}
35390
35391
35392template <int spacedim, typename Number>
35393void
35395 const Vector<Number> &b) const
35396{
35397 Assert(state == HMatrixSupport::lu, ExcInvalidHMatrixState(state));
35398
35399 x = b;
35400 // @p L has unit diagonal.
35401 solve_by_forward_substitution(x, true);
35402 // @p U has non-unit diagonal.
35403 solve_by_backward_substitution(x, false);
35404}
35405
35406
35407template <int spacedim, typename Number>
35408void
35410 const Vector<Number> &b) const
35411{
35412 Assert(state == HMatrixSupport::cholesky,
35413 ExcMessage(std::string("Invalid H-matrix state: ") +
35414 std::string(HMatrixSupport::state_name(state))));
35415
35416 x = b;
35417 solve_cholesky_by_forward_substitution(x);
35418 solve_cholesky_by_backward_substitution(x);
35419}
35420
35421
35422template <int spacedim, typename Number>
35423void
35426 const size_type fixed_rank_k)
35427{
35428 AssertDimension(m, n);
35429
35442 if (*(bc_node->get_data_reference().get_tau_node()) ==
35443 *(bc_node->get_data_reference().get_sigma_node()) &&
35444 bc_node->is_leaf())
35445 {
35446 Assert(type == FullMatrixType, ExcInvalidHMatrixType(type));
35447
35448 this->fullmatrix->invert_by_gauss_elim(*(M_inv.fullmatrix));
35449 }
35450 else
35451 {
35452 AssertDimension(get_n_row_blocks(), get_n_col_blocks());
35453
35458 const size_type k = get_n_col_blocks();
35459
35463 for (size_type l = 0; l < k; l++)
35464 {
35490 const size_type diag_block_index_in_submatrices = l + l * k;
35491 submatrices[diag_block_index_in_submatrices]->_invert_by_gauss_elim(
35492 *(M_inv.submatrices[diag_block_index_in_submatrices]),
35493 fixed_rank_k);
35494
35503 for (size_type j = l + 1; j < k; j++)
35504 {
35506 new HMatrix<spacedim, Number>(submatrices[j + l * k]->bc_node,
35507 fixed_rank_k);
35508 M_inv.submatrices[diag_block_index_in_submatrices]
35509 ->mmult_level_conserving(*C,
35510 *(submatrices[j + l * k]),
35511 fixed_rank_k);
35512
35516 *(submatrices[j + l * k]) = std::move(*C);
35517
35518 delete C;
35519 }
35520
35526 for (size_type j = 0; j < l; j++)
35527 {
35529 M_inv.submatrices[j + l * k]->bc_node, fixed_rank_k);
35530 M_inv.submatrices[diag_block_index_in_submatrices]
35531 ->mmult_level_conserving(*C,
35532 *(M_inv.submatrices[j + l * k]),
35533 fixed_rank_k);
35534
35538 *(M_inv.submatrices[j + l * k]) = std::move(*C);
35539
35540 delete C;
35541 }
35542
35548 for (size_type i = l + 1; i < k; i++)
35549 {
35550 for (size_type j = 0; j <= l; j++)
35551 {
35553 M_inv.submatrices[j + i * k]->bc_node, fixed_rank_k);
35554 submatrices[l + i * k]->mmult_level_conserving(
35555 *C, *(M_inv.submatrices[j + l * k]), fixed_rank_k);
35556 M_inv.submatrices[j + i * k]->add(-1.0, *C, fixed_rank_k);
35557
35558 delete C;
35559 }
35560
35561 for (size_type j = l + 1; j < k; j++)
35562 {
35564 submatrices[j + i * k]->bc_node, fixed_rank_k);
35565 submatrices[l + i * k]->mmult_level_conserving(
35566 *C, *(submatrices[j + l * k]), fixed_rank_k);
35567 submatrices[j + i * k]->add(-1.0, *C, fixed_rank_k);
35568
35569 delete C;
35570 }
35571 }
35572 }
35573
35577 for (size_type l = k - 1; l > 0; l--)
35578 {
35582 size_type i = l - 1;
35583 while (true)
35584 {
35585 for (size_type j = 0; j < k; j++)
35586 {
35588 M_inv.submatrices[j + i * k]->bc_node, fixed_rank_k);
35589 submatrices[l + i * k]->mmult_level_conserving(
35590 *C, *(M_inv.submatrices[j + l * k]), fixed_rank_k);
35591 M_inv.submatrices[j + i * k]->add(-1.0, *C, fixed_rank_k);
35592
35593 delete C;
35594 }
35595
35596 if (i == 0)
35597 {
35598 break;
35599 }
35600 else
35601 {
35602 i--;
35603 }
35604 }
35605 }
35606 }
35607}
35608
35609
35610template <int spacedim, typename Number>
35611void
35614 const unsigned int fixed_rank_k)
35615{
35616 coarsen_to_partition(subtree.get_leaf_set(), fixed_rank_k);
35617 build_leaf_set();
35618 link_hmat_nodes_on_same_levels();
35619}
35620
35621
35622template <int spacedim, typename Number>
35623void
35625 const std::vector<
35627 &partition,
35628 const unsigned int fixed_rank_k)
35629{
35637 if (find_pointer_data(partition.begin(), partition.end(), this->bc_node) !=
35638 partition.end())
35639 {
35645 convertHMatBlockToRkMatrix(this, fixed_rank_k);
35646 }
35647 else
35648 {
35654 for (HMatrix *submatrix : submatrices)
35655 {
35656 submatrix->coarsen_to_partition(partition, fixed_rank_k);
35657 }
35658 }
35659}
35660
35661
35662template <int spacedim, typename Number>
35663void
35665{
35666 const HMatrixSupport::Property top_hmat_property = this->property;
35667
35668 std::queue<HMatrix<spacedim, Number> *> work_queue;
35669
35670 if (submatrices.size() > 0)
35671 {
35672 work_queue.push(this);
35673
35674 while (!work_queue.empty())
35675 {
35676 HMatrix<spacedim, Number> *current_hmat_node = work_queue.front();
35677 work_queue.pop();
35678
35683 if (work_queue.size() > 0)
35684 {
35685 HMatrix<spacedim, Number> *next_hmat_node = work_queue.front();
35686 if (current_hmat_node->bc_node->get_level() ==
35687 next_hmat_node->bc_node->get_level())
35688 {
35689 current_hmat_node->next_same_level_hmat_node = next_hmat_node;
35690 }
35691 else
35692 {
35693 current_hmat_node->next_same_level_hmat_node = nullptr;
35694 }
35695 }
35696 else
35697 {
35698 current_hmat_node->next_same_level_hmat_node = nullptr;
35699 }
35700
35704 for (auto hmat : current_hmat_node->submatrices)
35705 {
35706 switch (top_hmat_property)
35707 {
35708 case HMatrixSupport::Property::general:
35709 work_queue.push(hmat);
35710
35711 break;
35712 case HMatrixSupport::Property::symmetric:
35713 case HMatrixSupport::Property::hermite_symmetric:
35714 case HMatrixSupport::Property::lower_triangular:
35715 if (hmat->block_type ==
35716 HMatrixSupport::BlockType::diagonal_block ||
35717 hmat->block_type ==
35718 HMatrixSupport::BlockType::lower_triangular_block)
35719 {
35720 work_queue.push(hmat);
35721 }
35722
35723 break;
35724 case HMatrixSupport::Property::upper_triangular:
35725 if (hmat->block_type ==
35726 HMatrixSupport::BlockType::diagonal_block ||
35727 hmat->block_type ==
35728 HMatrixSupport::BlockType::upper_triangular_block)
35729 {
35730 work_queue.push(hmat);
35731 }
35732
35733 break;
35734 default:
35735 Assert(false, ExcInvalidHMatrixProperty(top_hmat_property));
35736
35737 break;
35738 }
35739 }
35740 }
35741 }
35742}
35743
35744
35745template <int spacedim, typename Number>
35746void
35748 const HMatrixSupport::Property top_hmat_property)
35749{
35750 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
35751 ExcInvalidHMatrixBlockType(block_type));
35752
35757 HMatrix<spacedim, Number> *current_hmat_node_on_same_row = this;
35758 HMatrix<spacedim, Number> *current_hmat_node_on_same_column = this;
35759
35760 this->next_same_level_same_row_hmat_node = nullptr;
35761 this->next_same_level_same_column_hmat_node = nullptr;
35762 this->previous_same_level_same_row_hmat_node = nullptr;
35763 this->previous_same_level_same_column_hmat_node = nullptr;
35764
35765 HMatrix<spacedim, Number> *current_hmat_node_on_same_level =
35766 this->next_same_level_hmat_node;
35767
35768 while (current_hmat_node_on_same_level != nullptr)
35769 {
35775 if (top_hmat_property == HMatrixSupport::Property::general ||
35776 top_hmat_property == HMatrixSupport::Property::upper_triangular)
35777 {
35782 if (*current_hmat_node_on_same_level->row_index_range ==
35783 *this->row_index_range)
35784 {
35790 Assert((*current_hmat_node_on_same_level->col_index_range)[0] >=
35791 (*this->col_index_range)[1],
35792 ExcInternalError());
35793
35794 current_hmat_node_on_same_row
35796 current_hmat_node_on_same_level;
35797 current_hmat_node_on_same_level
35799 current_hmat_node_on_same_row;
35800
35804 current_hmat_node_on_same_row =
35805 current_hmat_node_on_same_row
35807 }
35808 }
35809
35815 if (top_hmat_property == HMatrixSupport::Property::general ||
35816 top_hmat_property == HMatrixSupport::Property::symmetric ||
35817 top_hmat_property == HMatrixSupport::Property::hermite_symmetric ||
35818 top_hmat_property == HMatrixSupport::Property::lower_triangular)
35819 {
35824 if (*current_hmat_node_on_same_level->col_index_range ==
35825 *this->col_index_range)
35826 {
35832 Assert((*current_hmat_node_on_same_level->row_index_range)[0] >=
35833 (*this->row_index_range)[1],
35834 ExcInternalError());
35835
35836 current_hmat_node_on_same_column
35838 current_hmat_node_on_same_level;
35839 current_hmat_node_on_same_level
35841 current_hmat_node_on_same_column;
35842
35846 current_hmat_node_on_same_column =
35847 current_hmat_node_on_same_column
35849 }
35850 }
35851
35855 current_hmat_node_on_same_level =
35856 current_hmat_node_on_same_level->next_same_level_hmat_node;
35857 }
35858
35862 if (submatrices.size() > 0)
35863 {
35864 const unsigned int n_row_blocks = get_n_row_blocks();
35865 const unsigned int n_col_blocks = get_n_col_blocks();
35866
35867 for (size_type i = 0; i < n_row_blocks; i++)
35868 {
35869 submatrices[i * n_col_blocks + i]
35870 ->link_hmat_nodes_on_cross_from_diagonal_blocks(top_hmat_property);
35871 }
35872 }
35873}
35874
35875
35876template <int spacedim, typename Number>
35879{
35880 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
35881 ExcInvalidHMatrixBlockType(block_type));
35882
35883 HMatrix<spacedim, Number> *current_node = this;
35884 while (true)
35885 {
35886 if (current_node->submatrices.size() == 0)
35887 return current_node;
35888 else
35889 current_node = current_node->submatrices[0];
35890 }
35891}
35892
35893
35894template <int spacedim, typename Number>
35897{
35898 Assert(block_type == HMatrixSupport::BlockType::diagonal_block,
35899 ExcInvalidHMatrixBlockType(block_type));
35900
35901 const HMatrix<spacedim, Number> *current_node = this;
35902 while (true)
35903 {
35904 if (current_node->submatrices.size() == 0)
35905 return current_node;
35906 else
35907 current_node = current_node->submatrices[0];
35908 }
35909}
35910
35911
35912template <int spacedim, typename Number>
35913void
35915{
35916 leaf_set.clear();
35917 near_field_leaf_set.clear();
35918 far_field_leaf_set.clear();
35919
35921 {
35922 case SpaceFillingCurveType::Z: {
35923 _build_leaf_set_z_traversal(leaf_set,
35924 near_field_leaf_set,
35925 far_field_leaf_set,
35926 property);
35927
35928 break;
35929 }
35930 case SpaceFillingCurveType::Hilbert: {
35934 _build_leaf_set_hilbert_traversal(leaf_set,
35935 near_field_leaf_set,
35936 far_field_leaf_set,
35937 HilbertBlockType::A,
35938 property);
35939
35940 break;
35941 }
35942 }
35943}
35944
35945
35946template <int spacedim, typename Number>
35947inline std::vector<HMatrix<spacedim, Number> *> &
35949{
35950 return leaf_set;
35951}
35952
35953
35954template <int spacedim, typename Number>
35955inline const std::vector<HMatrix<spacedim, Number> *> &
35957{
35958 return leaf_set;
35959}
35960
35961
35962template <int spacedim, typename Number>
35963inline std::vector<HMatrix<spacedim, Number> *> &
35965{
35966 return near_field_leaf_set;
35967}
35968
35969
35970template <int spacedim, typename Number>
35971inline const std::vector<HMatrix<spacedim, Number> *> &
35973{
35974 return near_field_leaf_set;
35975}
35976
35977
35978template <int spacedim, typename Number>
35979inline std::vector<HMatrix<spacedim, Number> *> &
35981{
35982 return far_field_leaf_set;
35983}
35984
35985
35986template <int spacedim, typename Number>
35987inline const std::vector<HMatrix<spacedim, Number> *> &
35989{
35990 return far_field_leaf_set;
35991}
35992
35993template <int spacedim, typename Number>
35994inline std::array<types::global_dof_index, 2> *
35996{
35997 return row_index_range;
35998}
35999
36000
36001template <int spacedim, typename Number>
36002inline const std::array<types::global_dof_index, 2> *
36004{
36005 return row_index_range;
36006}
36007
36008
36009template <int spacedim, typename Number>
36010inline std::array<types::global_dof_index, 2> *
36012{
36013 return col_index_range;
36014}
36015
36016
36017template <int spacedim, typename Number>
36018inline const std::array<types::global_dof_index, 2> *
36020{
36021 return col_index_range;
36022}
36023
36024
36025template <int spacedim, typename Number>
36026typename std::vector<HMatrix<spacedim, Number> *>::iterator
36028 const BlockCluster<spacedim, real_type> &block_cluster)
36029{
36030 typename std::vector<HMatrix<spacedim, Number> *>::iterator iter;
36031 for (iter = leaf_set.begin(); iter != leaf_set.end(); iter++)
36032 {
36045 if ((*iter)->bc_node != nullptr)
36046 {
36047 if ((*iter)->bc_node->get_data_reference() == block_cluster)
36048 {
36049 break;
36050 }
36051 }
36052 }
36053
36054 return iter;
36055}
36056
36057
36058template <int spacedim, typename Number>
36059typename std::vector<HMatrix<spacedim, Number> *>::const_iterator
36061 const BlockCluster<spacedim, real_type> &block_cluster) const
36062{
36063 for (typename std::vector<HMatrix<spacedim, Number> *>::const_iterator iter =
36064 leaf_set.cbegin();
36065 iter != leaf_set.cend();
36066 iter++)
36067 {
36080 if ((*iter)->bc_node != nullptr)
36081 {
36082 if ((*iter)->bc_node->get_data_reference() == block_cluster)
36083 {
36084 return iter;
36085 }
36086 }
36087 }
36088}
36089
36090
36091template <int spacedim, typename Number>
36092void
36094{
36104 for (HMatrix *hmat_leaf_node : leaf_set)
36105 {
36109 RefineHMatrixWrtExtendedBlockClusterTree(hmat_leaf_node, hmat_leaf_node);
36110
36115 if (hmat_leaf_node->submatrices.size() > 0)
36116 {
36124 switch (hmat_leaf_node->type)
36125 {
36126 case FullMatrixType: {
36127 delete hmat_leaf_node->fullmatrix;
36128 hmat_leaf_node->fullmatrix = nullptr;
36129
36130 break;
36131 }
36132 case RkMatrixType: {
36133 delete hmat_leaf_node->rkmatrix;
36134 hmat_leaf_node->rkmatrix = nullptr;
36135
36136 break;
36137 }
36138 default: {
36139 Assert(false, ExcInvalidHMatrixType(hmat_leaf_node->type));
36140
36141 break;
36142 }
36143 }
36144
36145 hmat_leaf_node->type = HierarchicalMatrixType;
36146 }
36147 }
36148
36154 build_leaf_set();
36155 link_hmat_nodes_on_same_levels();
36156
36161}
36162
36163
36164template <int spacedim, typename Number>
36165void
36169 const unsigned int fixed_rank_k2)
36170{
36175 std::vector<typename BlockClusterTree<spacedim, real_type>::node_pointer_type>
36176 target_leaf_set(bct2.get_leaf_set());
36177
36186 if (bct1.extend_finer_than_partition(target_leaf_set))
36187 {
36188 this->refine_to_supertree();
36189 }
36190
36196 bool is_bct2_extended = bct2.extend_to_finer_partition(bct1.get_leaf_set());
36197
36217 HMatrix<spacedim, Number> hmat_new(bct2, std::move(*this));
36218
36219 if (is_bct2_extended)
36220 {
36225 hmat_new.coarsen_to_partition(target_leaf_set, fixed_rank_k2);
36226 hmat_new.build_leaf_set();
36228
36235 // std::ofstream out1("target_bct_with_extension.dat");
36236 // bct2.write_leaf_set(out1);
36237 // out1.close();
36238 // std::cout << "=== bct2 with extension ===\n";
36239 // std::cout << "Number of nodes: " << bct2.get_node_num()
36240 // << "\nDepth: " << bct2.get_depth()
36241 // << "\nMax level: " << bct2.get_max_level() <<
36242 // std::endl;
36243 bct2.prune_to_partition(target_leaf_set, true);
36244 // std::ofstream out2("target_bct_after_pruning.dat");
36245 // bct2.write_leaf_set(out2);
36246 // out2.close();
36247 // std::cout << "=== bct2 after pruning ===\n";
36248 // std::cout << "Number of nodes: " << bct2.get_node_num()
36249 // << "\nDepth: " << bct2.get_depth()
36250 // << "\nMax level: " << bct2.get_max_level() <<
36251 // std::endl;
36252 }
36253
36258 (*this) = std::move(hmat_new);
36259}
36260
36261
36262template <int spacedim, typename Number>
36263void
36265 const HMatrix<spacedim, Number> *M1,
36266 const HMatrix<spacedim, Number> *M2)
36267{
36268 std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
36269 current_hmat_pair(const_cast<HMatrix<spacedim, Number> *>(M1),
36270 const_cast<HMatrix<spacedim, Number> *>(M2));
36271
36272 typename std::vector<std::pair<HMatrix<spacedim, Number> *,
36273 HMatrix<spacedim, Number> *>>::iterator
36274 matched_hmat_pair_iter =
36275 std::find(Sigma_P.begin(), Sigma_P.end(), current_hmat_pair);
36276
36277 if (matched_hmat_pair_iter != Sigma_P.end())
36278 {
36279 Sigma_P.erase(matched_hmat_pair_iter);
36280 }
36281}
36282
36283
36284template <int spacedim, typename Number>
36285void
36287 const std::pair<const HMatrix<spacedim, Number> *,
36288 const HMatrix<spacedim, Number> *> &hmat_pair)
36289{
36290 typename std::vector<std::pair<HMatrix<spacedim, Number> *,
36291 HMatrix<spacedim, Number> *>>::iterator
36292 matched_hmat_pair_iter =
36293 std::find(Sigma_P.begin(), Sigma_P.end(), hmat_pair);
36294
36295 if (matched_hmat_pair_iter != Sigma_P.end())
36296 {
36297 Sigma_P.erase(matched_hmat_pair_iter);
36298 }
36299}
36300
36301
36302template <int spacedim, typename Number>
36305{
36306 TreeNodeSplitMode initial_split_mode, current_split_mode;
36307
36308 size_type counter = 0;
36309 for (const std::pair<HMatrix<spacedim, Number> *, HMatrix<spacedim, Number> *>
36310 &hmat_pair : Sigma_P)
36311 {
36312 if ((hmat_pair.first->bc_node->get_split_mode() == HorizontalSplitMode &&
36313 hmat_pair.second->bc_node->get_split_mode() == UnsplitMode) ||
36314 (hmat_pair.first->bc_node->get_split_mode() == CrossSplitMode &&
36315 hmat_pair.second->bc_node->get_split_mode() == HorizontalSplitMode))
36316 {
36317 current_split_mode = HorizontalSplitMode;
36318 }
36319 else if ((hmat_pair.first->bc_node->get_split_mode() == UnsplitMode &&
36320 hmat_pair.second->bc_node->get_split_mode() ==
36321 VerticalSplitMode) ||
36322 (hmat_pair.first->bc_node->get_split_mode() ==
36323 VerticalSplitMode &&
36324 hmat_pair.second->bc_node->get_split_mode() == CrossSplitMode))
36325 {
36326 current_split_mode = VerticalSplitMode;
36327 }
36328 else if ((hmat_pair.first->bc_node->get_split_mode() == CrossSplitMode &&
36329 hmat_pair.second->bc_node->get_split_mode() ==
36330 CrossSplitMode) ||
36331 (hmat_pair.first->bc_node->get_split_mode() ==
36332 HorizontalSplitMode &&
36333 hmat_pair.second->bc_node->get_split_mode() ==
36334 VerticalSplitMode))
36335 {
36336 current_split_mode = CrossSplitMode;
36337 }
36338 else
36339 {
36340 Assert(false,
36341 ExcMessage(
36342 "Inconsistent case met during H-matrix MM multiplication"));
36343 }
36344
36345 if (counter == 0)
36346 {
36347 initial_split_mode = current_split_mode;
36348 }
36349 else if (current_split_mode != initial_split_mode)
36350 {
36351 Assert(false,
36352 ExcMessage(
36353 "Inconsistent case met during H-matrix MM multiplication"));
36354 }
36355
36356 counter++;
36357 }
36358
36359 return initial_split_mode;
36360}
36361
36362template <int spacedim, typename Number>
36363std::size_t
36365{
36366 std::size_t memory_for_hmat_node = 0;
36367
36372 if (type == FullMatrixType)
36373 {
36374 memory_for_hmat_node += this->fullmatrix->memory_consumption();
36375 }
36376 else if (type == RkMatrixType)
36377 {
36378 memory_for_hmat_node += this->rkmatrix->memory_consumption();
36379 }
36380
36384 memory_for_hmat_node +=
36385 sizeof(*this) +
36386 (MemoryConsumption::memory_consumption(leaf_set) - sizeof(leaf_set)) +
36387 (MemoryConsumption::memory_consumption(submatrices) - sizeof(submatrices)) +
36388 (MemoryConsumption::memory_consumption(near_field_leaf_set) -
36389 sizeof(near_field_leaf_set)) +
36390 (MemoryConsumption::memory_consumption(far_field_leaf_set) -
36391 sizeof(far_field_leaf_set)) +
36392 (Tind.memory_consumption() - sizeof(Tind)) +
36393 (MemoryConsumption::memory_consumption(Sigma_P) - sizeof(Sigma_P)) +
36394 (MemoryConsumption::memory_consumption(Sigma_R) - sizeof(Sigma_R)) +
36395 (MemoryConsumption::memory_consumption(Sigma_F) - sizeof(Sigma_F)) +
36396 sizeof(data_for_vmult_or_tvmult_threads);
36397
36398 if (data_for_vmult_or_tvmult_threads != nullptr)
36399 memory_for_hmat_node +=
36400 MemoryConsumption::memory_consumption(*data_for_vmult_or_tvmult_threads);
36401
36402 return memory_for_hmat_node;
36403}
36404
36405
36406template <int spacedim, typename Number>
36407std::size_t
36409{
36410 std::size_t total_memory = 0;
36411
36412 total_memory += memory_consumption_of_current_hmat_node();
36413
36414 for (auto submatrix : submatrices)
36415 {
36416 total_memory += submatrix->memory_consumption();
36417 }
36418
36419 return total_memory;
36420}
36421
36422
36423template <int spacedim, typename Number>
36424std::size_t
36426{
36427 std::size_t total_memory = 0;
36428
36429 for (auto hmat : leaf_set)
36430 {
36431 total_memory += hmat->memory_consumption();
36432 }
36433
36434 return total_memory;
36435}
36436
36437
36438template <int spacedim, typename Number>
36439std::size_t
36441{
36442 std::size_t total_memory = 0;
36443
36444 for (auto hmat : near_field_leaf_set)
36445 {
36446 total_memory += hmat->memory_consumption();
36447 }
36448
36449 return total_memory;
36450}
36451
36452
36453template <int spacedim, typename Number>
36454std::size_t
36456{
36457 std::size_t total_memory = 0;
36458
36459 for (auto hmat : far_field_leaf_set)
36460 {
36461 total_memory += hmat->memory_consumption();
36462 }
36463
36464 return total_memory;
36465}
36466
36467HBEM_NS_CLOSE
36468
36469#endif /* HIERBEM_INCLUDE_HMATRIX_HMATRIX_H_ */
std::make_unsigned< types::blas_int >::type size_type
Definition: aca_plus.hcu:90
Implementation of the class BlockCluster.
Implementation of the class BlockClusterTree.
void split_block_cluster_node(TreeNode< BlockCluster< spacedim, Number >, BlockClusterTree< spacedim, Number >::child_num > *bc_node, BlockClusterTree< spacedim, Number > &bc_tree, const TreeNodeSplitMode split_mode, const bool if_add_child_nodes_to_leaf_set=true)
Class for block cluster tree.
std::vector< node_pointer_type > & get_leaf_set()
void categorize_near_and_far_field_sets()
bool extend_finer_than_partition(const std::vector< node_pointer_type > &partition)
node_pointer_type get_root() const
unsigned int get_n_min() const
bool extend_to_finer_partition(const std::vector< node_pointer_type > &partition)
bool prune_to_partition(const std::vector< node_pointer_type > &partition, const bool is_partition_in_bct)
std::size_t memory_consumption() const
Definition: hmatrix.h:297
void cholesky_solve_upper_task(tbb::flow::graph &dag, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:34326
void set_property(const LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:19552
void convertToFullMatrix(MatrixType &M) const
Definition: hmatrix.h:18155
RkMatrix< Number > * get_rkmatrix()
Definition: hmatrix.h:19772
TaskNodePtr factorize_lu_or_cholesky_graph_node
Definition: hmatrix.h:4409
void solve_block_triangular_by_forward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_block_diagonal=true) const
Definition: hmatrix.h:31668
std::vector< RkMatrix< Number > * > Sigma_R
Definition: hmatrix.h:4397
void _convertToFullMatrix(MatrixType &M, const HMatrixSupport::Property top_hmat_property=HMatrixSupport::Property::general) const
Definition: hmatrix.h:18170
void solve_cholesky_by_backward_substitution(Vector< Number > &b) const
Definition: hmatrix.h:32269
std::vector< HMatrix< spacedim, Number > * > & get_submatrices()
Definition: hmatrix.h:19831
void solve_by_backward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_diagonal=false) const
Definition: hmatrix.h:32020
void Tvmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:26113
HMatrix< spacedim, Number > * previous_same_level_same_column_hmat_node
Definition: hmatrix.h:4318
void set_current_matrix_property(const HMatrixSupport::Property property)
Definition: hmatrix.h:19129
void solve_cholesky_by_forward_substitution(Vector< Number > &b) const
Definition: hmatrix.h:31786
std::size_t memory_consumption_of_current_hmat_node() const
Definition: hmatrix.h:36364
HMatrix(const HMatrix< spacedim, Number > &H)
Definition: hmatrix.h:17974
void vmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x, const HMatrix< spacedim, Number > &starting_hmat, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:22066
void solve_block_triangular_by_backward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_block_diagonal=false) const
Definition: hmatrix.h:32146
void cholesky_update_task(tbb::flow::graph &dag, HMatrix< spacedim, Number > &diag_block, HMatrix< spacedim, Number > &diag_column_block1, HMatrix< spacedim, Number > &diag_column_block2, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:34370
void build_leaf_set()
Definition: hmatrix.h:35914
void Hvmult_serial_iterative(const Number2 beta, Vector< Number > &y, const Number3 alpha, const Vector< Number > &x) const
Calculate the top level -matrix/vector multiplication as by iterating over the leaf set.
Definition: hmatrix.h:28248
void add_for_parallel_lu_or_cholesky(const RkMatrix< Number > &B, const std::array< types::global_dof_index, 2 > &B_row_index_range, const std::array< types::global_dof_index, 2 > &B_col_index_range, const size_type fixed_rank_k, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29758
void h_h_mmult_reduction()
Definition: hmatrix.h:28729
void solve_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank, const bool is_unit_diagonal=true) const
Definition: hmatrix.h:30612
void _distribute_sigma_r_and_f_to_leaves(HMatrix< spacedim, Number > &starting_hmat, const unsigned int fixed_rank=0)
Definition: hmatrix.h:18760
HMatrix(const BlockClusterTree< spacedim, real_type > &bct, const unsigned int fixed_rank_k=1, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::undefined_block)
Definition: hmatrix.h:17632
void print_matrix_info_as_dot(std::ostream &out)
Definition: hmatrix.h:19958
HMatrix * find_col_diag_block_for_offdiag_block()
Definition: hmatrix.h:20581
void Tvmult(Vector< Number > &y, const Vector< Number > &x, const HMatrix< spacedim, Number > &starting_hmat, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:24651
void Hvmult(Vector< Number > &y, const Vector< Number > &x, const HMatrix< spacedim, Number > &starting_hmat, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:27169
HMatrix(HMatrix< spacedim, Number > &&H) noexcept
Definition: hmatrix.h:18011
void cholesky_build_update_to_factorize_dependencies(HMatrix< spacedim, Number > &factorize_block)
Definition: hmatrix.h:34422
HMatrix * find_row_diag_block_for_offdiag_block()
Definition: hmatrix.h:20419
void lu_build_update_to_solve_upper_or_lower_dependencies(HMatrix< spacedim, Number > &solve_upper_or_lower_block)
Definition: hmatrix.h:33475
void solve_transpose_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank) const
Definition: hmatrix.h:31120
void Tvmult_task_parallel(const Number2 beta, Vector< Number > &y, const Number3 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:25821
std::array< types::global_dof_index, 2 > * get_row_index_range()
Definition: hmatrix.h:35995
HMatrix< spacedim, Number > * get_top_left_leaf_node()
Get the pointer to the top left leaf node in the -matrix.
Definition: hmatrix.h:35878
void mTmult_level_conserving(HMatrix< spacedim, Number > &C, HMatrix< spacedim, Number > &B, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29363
HMatrix(typename BlockClusterTree< spacedim, real_type >::node_const_pointer_type bc_node, HMatrix< spacedim, Number > &&H, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::undefined_block)
Definition: hmatrix.h:17891
void solve_cholesky_by_backward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat) const
Definition: hmatrix.h:32369
void lu_assign_update_to_solve_and_factorize_dependencies()
Definition: hmatrix.h:33552
SpaceFillingCurveType
Definition: hmatrix.h:117
@ Hilbert
Definition: hmatrix.h:125
void link_hmat_nodes_on_cross_from_diagonal_blocks(const HMatrixSupport::Property top_hmat_property)
Definition: hmatrix.h:35747
HMatrixSupport::Property get_property() const
Definition: hmatrix.h:19121
LAPACKFullMatrixExt< Number > * fullmatrix
Definition: hmatrix.h:4350
unsigned int get_n_row_blocks() const
Definition: hmatrix.h:19101
void _compute_cholesky_factorization(HMatrix< spacedim, Number > &L, const unsigned int fixed_rank) const
Definition: hmatrix.h:33644
void h_h_mmult_horizontal_split(BlockClusterTree< spacedim, real_type > &bc_tree)
Definition: hmatrix.h:28811
void vmult(Vector< Number > &y, const Vector< Number > &x, const HMatrix< spacedim, Number > &starting_hmat, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:22053
void Tvmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:23677
void reinit(const BlockClusterTree< spacedim, real_type > &bct, const unsigned int fixed_rank_k=1, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::diagonal_block)
std::vector< std::pair< HMatrix< spacedim, Number > *, HMatrix< spacedim, Number > * > > Sigma_P
Definition: hmatrix.h:4391
void add(HMatrix< spacedim, Number > &C, const RkMatrix< Number > &B, const size_type fixed_rank_k)
Definition: hmatrix.h:30202
void cholesky_build_update_to_solve_upper_dependencies(HMatrix< spacedim, Number > &solve_upper_block)
Definition: hmatrix.h:34463
void truncate_to_rank_diag_preserve_positive_definite(size_type new_rank, const bool is_only_handle_tril=true)
Definition: hmatrix.h:20793
void solve_transpose_by_forward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat) const
Definition: hmatrix.h:30864
void vmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:23634
double compute_near_field_hmat_assembly_task_cost(const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:34779
void Tvmult_add(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:26129
void compute_leaf_set_vmult_or_Tvmult_task_costs(std::vector< double > &task_costs) const
Definition: hmatrix.h:34740
TaskNodePtr solve_upper_or_lower_lu_or_cholesky_graph_node
Definition: hmatrix.h:4414
std::array< types::global_dof_index, 2 > * get_col_index_range()
Definition: hmatrix.h:36011
std::vector< HMatrix< spacedim, Number > * > submatrices
Definition: hmatrix.h:4284
void solve_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b, const bool is_unit_diagonal=true) const
Definition: hmatrix.h:30329
std::vector< HMatrix< spacedim, Number > * >::const_iterator find_block_cluster_in_leaf_set(const BlockCluster< spacedim, real_type > &block_cluster) const
Definition: hmatrix.h:36060
HMatrix< spacedim, Number > * next_same_level_same_row_hmat_node
Definition: hmatrix.h:4300
void Tvmult_serial_iterative(const Number2 beta, Vector< Number > &y, const Number3 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:25689
double compute_far_field_hmat_vmult_or_Tvmult_task_cost(const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:34681
void reinit(typename BlockClusterTree< spacedim, real_type >::node_const_pointer_type bc_node, const unsigned int fixed_rank_k=1, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::undefined_block)
Definition: hmatrix.h:18074
void clear_lu_or_cholesky_task_nodes_in_hmat()
Definition: hmatrix.h:19035
void write_leaf_set_by_iteration(std::ostream &out, const real_type singular_value_threshold=0.) const
Definition: hmatrix.h:20388
std::vector< UpdateTaskNodeForLUOrCholesky > update_lu_or_cholesky_graph_nodes
Definition: hmatrix.h:4419
bool is_leaf() const
Definition: hmatrix.h:19084
HMatrix(const BlockClusterTree< spacedim, real_type > &bct, HMatrix< spacedim, Number > &&H, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::diagonal_block)
Definition: hmatrix.h:17933
void h_h_mmult_vertical_split(BlockClusterTree< spacedim, real_type > &bc_tree)
Definition: hmatrix.h:28919
void solve_cholesky_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b) const
Definition: hmatrix.h:31797
void add(const RkMatrix< Number > &B, const size_type fixed_rank_k, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:30068
std::make_unsigned< types::blas_int >::type size_type
Definition: hmatrix.h:109
void clear_lu_or_cholesky_task_nodes()
Definition: hmatrix.h:19022
void compute_vmult_contributing_index_ranges_from_all_threads(const unsigned int thread_no)
Definition: hmatrix.h:35025
HMatrix(const BlockClusterTree< spacedim, real_type > &bct, const LAPACKFullMatrixExt< Number > &M, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::diagonal_block)
Definition: hmatrix.h:17761
void compute_cholesky_factorization(HMatrix< spacedim, Number > &L, const unsigned int fixed_rank)
Definition: hmatrix.h:33785
std::vector< HMatrix< spacedim, Number > * > leaf_set
Definition: hmatrix.h:4328
void solve_transpose_by_forward_substitution(Vector< Number > &b) const
Definition: hmatrix.h:30776
void lu_factorize_diagonal_block_task(tbb::flow::graph &dag, std::mutex &log_stream_lock)
Definition: hmatrix.h:33172
std::mutex update_lock
Definition: hmatrix.h:4425
void Tvmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x, const HMatrix< spacedim, Number > &starting_hmat, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:24664
void truncate_to_rank(size_type new_rank)
Definition: hmatrix.h:20744
const RkMatrix< Number > * get_rkmatrix() const
Definition: hmatrix.h:19780
unsigned int submatrix_index
Definition: hmatrix.h:4323
HMatrix(typename BlockClusterTree< spacedim, real_type >::node_const_pointer_type bc_node, const unsigned int fixed_rank_k=1, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::undefined_block)
Definition: hmatrix.h:17673
void _build_leaf_set_hilbert_traversal(std::vector< HMatrix * > &total_leaf_set, std::vector< HMatrix * > &total_near_field_leaf_set, std::vector< HMatrix * > &total_far_field_leaf_set, HilbertBlockType current_hilbert_block_type, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:18515
void solve_transpose_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &X, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank) const
Definition: hmatrix.h:30961
void h_h_mmult_cross_split(BlockClusterTree< spacedim, real_type > &bc_tree)
Definition: hmatrix.h:29027
void distribute_all_non_leaf_nodes_sigma_r_and_f_to_leaves(const unsigned int fixed_rank=0)
Definition: hmatrix.h:18687
std::vector< HMatrix< spacedim, Number > * > near_field_leaf_set
Definition: hmatrix.h:4333
void solve_block_triangular_by_backward_substitution(Vector< Number > &x, const Vector< Number > &b, const bool is_unit_block_diagonal=false) const
Definition: hmatrix.h:32134
void _compute_cholesky_factorization(const unsigned int fixed_rank)
Definition: hmatrix.h:33804
void compute_tvmult_contributing_index_ranges_from_all_threads(const unsigned int thread_no)
Definition: hmatrix.h:35055
void set_default_vmult_strategy()
Definition: hmatrix.h:21032
void set_current_matrix_property(const LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:19138
HMatrix< spacedim, Number > & operator=(HMatrix< spacedim, Number > &&H) noexcept
Definition: hmatrix.h:18095
void Hvmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x, const HMatrix< spacedim, Number > &starting_hmat, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:27182
HMatrixSupport::BlockType block_type
Definition: hmatrix.h:4269
void print_as_formatted_full_matrix(std::ostream &out, const std::string &name, const unsigned int precision=8, const bool scientific=true, const unsigned int width=0, const char *zero_string="0", const double denominator=1., const double threshold=0.) const
Definition: hmatrix.h:19992
std::vector< HMatrix< spacedim, Number > * > far_field_leaf_set
Definition: hmatrix.h:4338
TreeNodeSplitMode determine_mm_split_mode_from_Sigma_P()
Definition: hmatrix.h:36304
std::array< types::global_dof_index, 2 > * col_index_range
Definition: hmatrix.h:4367
std::array< types::global_dof_index, 2 > * row_index_range
Definition: hmatrix.h:4361
void get_column_index_range_for_leaf_set_interval(const std::pair< int64_t, int64_t > &interval, const unsigned int thread_no)
Definition: hmatrix.h:34980
HMatrix< spacedim, Number > * parent
Definition: hmatrix.h:4289
void calc_rank_upper_bound_for_rkmatrices() const
Definition: hmatrix.h:19788
void Tvmult(Vector< Number > &y, const Vector< Number > &x) const
Definition: hmatrix.h:26084
bool is_current_hmat_node_nonemtpy(const HMatrixSupport::Property top_hmat_property=HMatrixSupport::Property::general) const
Definition: hmatrix.h:18409
BlockClusterTree< spacedim, real_type > Tind
Definition: hmatrix.h:4383
void add(const Number b, const RkMatrix< Number > &B, const std::array< types::global_dof_index, 2 > &B_row_index_range, const std::array< types::global_dof_index, 2 > &B_col_index_range, const size_type fixed_rank_k, const bool is_result_matrix_store_tril_only=false) const
Definition: hmatrix.h:29941
void Hvmult(Vector< Number > &y, const Vector< Number > &x) const
Definition: hmatrix.h:28669
void lu_build_solve_lower_to_update_dependencies(HMatrix< spacedim, Number > &update_block)
Definition: hmatrix.h:33399
void compute_near_field_leaf_set_assembly_task_costs(std::vector< double > &task_costs) const
Definition: hmatrix.h:34835
void mTmult_level_conserving(HMatrix< spacedim, Number > &C, const Number alpha, HMatrix< spacedim, Number > &B, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29376
void write_leaf_set(std::ostream &out, const real_type singular_value_threshold=0.) const
Definition: hmatrix.h:20353
void print_formatted(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const unsigned int width=0, const char *zero_string=" ", const double denominator=1., const double threshold=0.) const
Definition: hmatrix.h:19847
void mmult_level_conserving(HMatrix< spacedim, Number > &C, const Number alpha, HMatrix< spacedim, Number > &B, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29335
void release()
Definition: hmatrix.h:18885
HMatrix(typename BlockClusterTree< spacedim, real_type >::node_const_pointer_type bc_node, const LAPACKFullMatrixExt< Number > &M, const unsigned int fixed_rank_k, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::undefined_block)
Definition: hmatrix.h:17806
void vmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:21064
void convert_between_different_block_cluster_trees(BlockClusterTree< spacedim, real_type > &bct1, BlockClusterTree< spacedim, real_type > &bct2, const unsigned int fixed_rank_k2=1)
Definition: hmatrix.h:36166
HMatrix< spacedim, Number > & operator=(const HMatrix< spacedim, Number > &H)
Definition: hmatrix.h:18140
void solve_lu(Vector< Number > &x, const Vector< Number > &b) const
Definition: hmatrix.h:35394
const std::vector< HMatrix< spacedim, Number > * > & get_leaf_set() const
Definition: hmatrix.h:35956
void assign_node_ids_for_dot()
Definition: hmatrix.h:20060
void solve_cholesky_by_backward_substitution(Vector< Number > &x, const Vector< Number > &b) const
Definition: hmatrix.h:32358
void truncate_to_rank_off_diag_preserve_positive_definite(size_type new_rank, const bool is_compensate_diag_blocks=true)
Definition: hmatrix.h:20951
void set_current_matrix_block_type(const HMatrixSupport::BlockType block_type)
Definition: hmatrix.h:19664
void add(const Number b, const RkMatrix< Number > &B, const size_type fixed_rank_k, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:30103
HMatrixType type
Definition: hmatrix.h:4252
void solve_cholesky_by_backward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat) const
Definition: hmatrix.h:32461
static const unsigned int submatrix_index_invalid
Definition: hmatrix.h:911
void Hvmult(Vector< Number > &y, const Vector< Number > &x, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:26144
HMatrixSupport::State get_state() const
Definition: hmatrix.h:19632
void solve_block_triangular_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_block_diagonal=true) const
Definition: hmatrix.h:31771
bool is_root() const
Definition: hmatrix.h:19060
const std::array< types::global_dof_index, 2 > * get_row_index_range() const
Definition: hmatrix.h:36003
void vmult_task_parallel(const Number2 beta, Vector< Number > &y, const Number3 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:23286
tbb::flow::continue_node< tbb::flow::continue_msg > TaskNode
Definition: hmatrix.h:270
const std::array< types::global_dof_index, 2 > * get_col_index_range() const
Definition: hmatrix.h:36019
const std::vector< HMatrix< spacedim, Number > * > & get_submatrices() const
Definition: hmatrix.h:19839
void add(HMatrix< spacedim, Number > &C, const HMatrix< spacedim, Number > &B, const size_type fixed_rank_k) const
Definition: hmatrix.h:29431
void truncate_to_rank_preserve_positive_definite(size_type new_rank, const bool is_only_handle_tril=true)
Definition: hmatrix.h:20782
void solve_transpose_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b) const
Definition: hmatrix.h:30853
void add(const HMatrix< spacedim, Number > &B, const size_type fixed_rank_k) const
Definition: hmatrix.h:29529
LAPACKFullMatrixExt< Number > * get_fullmatrix()
Definition: hmatrix.h:19815
void remove_hmat_pair_from_mm_product_list(const HMatrix< spacedim, Number > *M1, const HMatrix< spacedim, Number > *M2)
Definition: hmatrix.h:36264
HMatrix(const BlockClusterTree< spacedim, real_type > &bct, const LAPACKFullMatrixExt< Number > &M, const unsigned int fixed_rank_k, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::diagonal_block)
Definition: hmatrix.h:17715
void vmult(Vector< Number > &y, const Vector< Number > &x) const
Definition: hmatrix.h:23605
HMatrix< spacedim, Number > * previous_same_level_same_row_hmat_node
Definition: hmatrix.h:4312
HMatrixSupport::BlockType get_block_type() const
Definition: hmatrix.h:19656
HMatrix< spacedim, Number > * next_same_level_hmat_node
Definition: hmatrix.h:4294
static SpaceFillingCurveType leaf_set_traversal_method
Definition: hmatrix.h:4246
void vmult_add(Vector< Number > &y, const Vector< Number > &x) const
Definition: hmatrix.h:23619
void coarsen_to_subtree(const BlockClusterTree< spacedim, real_type > &subtree, const unsigned int fixed_rank_k)
Definition: hmatrix.h:35612
void remove_hmat_pair_from_mm_product_list(const std::pair< const HMatrix< spacedim, Number > *, const HMatrix< spacedim, Number > * > &hmat_pair)
Definition: hmatrix.h:36286
void coarsen_to_partition(const std::vector< typename BlockClusterTree< spacedim, real_type >::node_pointer_type > &partition, const unsigned int fixed_rank_k)
Definition: hmatrix.h:35624
size_type m
Definition: hmatrix.h:4372
std::vector< LAPACKFullMatrixExt< Number > * > Sigma_F
Definition: hmatrix.h:4403
void solve_block_triangular_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b, const bool is_unit_block_diagonal=true) const
Definition: hmatrix.h:31656
void solve_block_triangular_by_backward_substitution(Vector< Number > &b, const bool is_unit_block_diagonal=false) const
Definition: hmatrix.h:32033
void Hvmult_add(Vector< Number > &y, const Vector< Number > &x) const
Definition: hmatrix.h:28683
void mmult(HMatrix< spacedim, Number > &C, HMatrix< spacedim, Number > &B, const BlockClusterTree< spacedim, real_type > &bct_a, const BlockClusterTree< spacedim, real_type > &bct_b, BlockClusterTree< spacedim, real_type > &bct_c, const unsigned int fixed_rank, const bool adding)
Definition: hmatrix.h:29298
RkMatrix< Number > * rkmatrix
Definition: hmatrix.h:4344
void print_current_matrix_info(std::ostream &out) const
Definition: hmatrix.h:19913
std::unique_ptr< HMatrixVmultStrategy< spacedim, Number > > vmult_strategy
Definition: hmatrix.h:4274
size_type get_m() const
Definition: hmatrix.h:19093
void set_property(const HMatrixSupport::Property property)
Definition: hmatrix.h:19178
std::size_t memory_consumption_of_far_field_leaf_set() const
Definition: hmatrix.h:36455
HMatrixType get_type() const
Definition: hmatrix.h:19052
void solve_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_diagonal=true) const
Definition: hmatrix.h:30434
void Hvmult_add(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:28714
void solve_transpose_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat) const
Definition: hmatrix.h:30948
void Hvmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:28698
void lu_solve_lower_task(tbb::flow::graph &dag, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:33267
std::size_t memory_consumption_of_near_field_leaf_set() const
Definition: hmatrix.h:36440
void compute_cholesky_dag(tbb::flow::graph &dag, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:33933
unsigned int get_n_col_blocks() const
Definition: hmatrix.h:19111
std::size_t memory_consumption_of_leaf_set() const
Definition: hmatrix.h:36425
void cholesky_assign_update_to_solve_and_factorize_dependencies()
Definition: hmatrix.h:34513
void print_leaf_set_info(std::ostream &out) const
Definition: hmatrix.h:20017
void Tvmult(Vector< Number > &y, const Vector< Number > &x, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:23665
HMatrixSupport::State state
Definition: hmatrix.h:4257
size_type n
Definition: hmatrix.h:4377
std::unique_ptr< std::vector< VmultOrTvmultThreadData > > data_for_vmult_or_tvmult_threads
Definition: hmatrix.h:4436
void solve_by_backward_substitution(Vector< Number > &x, const Vector< Number > &b, const bool is_unit_diagonal=false) const
Definition: hmatrix.h:31918
void solve_block_triangular_by_forward_substitution(Vector< Number > &b, const bool is_unit_block_diagonal=true) const
Definition: hmatrix.h:31560
void write_fullmatrix_leaf_node(std::ostream &out, const real_type singular_value_threshold=0.) const
Definition: hmatrix.h:20250
void compute_lu_factorization(const unsigned int fixed_rank)
Definition: hmatrix.h:32490
unsigned int compute_vmult_or_tvmult_thread_num(const bool is_vmult, const bool is_tvmult) const
Definition: hmatrix.h:35085
void compute_cholesky_factorization(const unsigned int fixed_rank)
Definition: hmatrix.h:33917
void lu_solve_upper_task(tbb::flow::graph &dag, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:33224
HMatrix< spacedim, Number > * next_same_level_same_column_hmat_node
Definition: hmatrix.h:4306
size_type get_n() const
Definition: hmatrix.h:19764
void add(const RkMatrix< Number > &B, const std::array< types::global_dof_index, 2 > &B_row_index_range, const std::array< types::global_dof_index, 2 > &B_col_index_range, const size_type fixed_rank_k, const bool is_result_matrix_store_tril_only=false) const
Definition: hmatrix.h:29620
void compute_far_field_leaf_set_assembly_task_costs(std::vector< double > &task_costs) const
Definition: hmatrix.h:34917
bool is_far_field() const
Definition: hmatrix.h:19076
void compute_cholesky_factorization_task_parallel(const unsigned int fixed_rank)
Definition: hmatrix.h:35311
void write_rkmatrix_leaf_node(std::ostream &out) const
Definition: hmatrix.h:20310
void lu_or_cholesky_build_solve_upper_to_update_dependencies(HMatrix< spacedim, Number > &update_block)
Definition: hmatrix.h:33358
void solve_cholesky(Vector< Number > &x, const Vector< Number > &b) const
Definition: hmatrix.h:35409
std::vector< HMatrix< spacedim, Number > * > & get_leaf_set()
Definition: hmatrix.h:35948
void solve_by_backward_substitution(Vector< Number > &b, const bool is_unit_diagonal=false) const
Definition: hmatrix.h:31834
void addsym_diag(const LAPACKFullMatrixExt< Number > &E)
Definition: hmatrix.h:30122
void set_state(const HMatrixSupport::State state)
Definition: hmatrix.h:19640
void solve_cholesky_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &X, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank) const
Definition: hmatrix.h:30755
void solve_cholesky_by_forward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat) const
Definition: hmatrix.h:31821
void _compute_lu_factorization(const unsigned int fixed_rank)
Definition: hmatrix.h:32615
void mmult_level_conserving(HMatrix< spacedim, Number > &C, HMatrix< spacedim, Number > &B, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29322
size_type dot_node_id
Definition: hmatrix.h:4279
void vmult_add(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:23650
BlockClusterTree< spacedim, real_type >::node_pointer_type bc_node
Definition: hmatrix.h:4355
double compute_near_field_hmat_vmult_or_Tvmult_task_cost(const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:34610
void refine_to_supertree()
Definition: hmatrix.h:36093
void Tmmult_level_conserving(HMatrix< spacedim, Number > &C, const Number alpha, HMatrix< spacedim, Number > &B, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29417
void compute_lu_dag(tbb::flow::graph &dag, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:32796
void solve_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &X, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank, const bool is_unit_diagonal=true) const
Definition: hmatrix.h:30447
const HMatrix< spacedim, Number > * get_top_left_leaf_node() const
Get the pointer to the top left leaf node in the -matrix.
Definition: hmatrix.h:35896
void set_property_for_converted_fullmatrix(LAPACKFullMatrixExt< Number > &M) const
Definition: hmatrix.h:20210
void Hvmult(Vector< Number > &y, const Number2 alpha, const Vector< Number > &x, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:26156
void print_matrix_info(std::ostream &out) const
Definition: hmatrix.h:19900
void link_hmat_nodes_on_same_levels()
Definition: hmatrix.h:35664
std::size_t memory_consumption() const
Definition: hmatrix.h:36408
void compute_lu_factorization_task_parallel(const unsigned int fixed_rank)
Definition: hmatrix.h:32715
void vmult(Vector< Number > &y, const Vector< Number > &x, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:21052
void _build_leaf_set_z_traversal(std::vector< HMatrix * > &total_leaf_set, std::vector< HMatrix * > &total_near_field_leaf_set, std::vector< HMatrix * > &total_far_field_leaf_set, const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:18469
void lu_update_task(tbb::flow::graph &dag, HMatrix< spacedim, Number > &diag_block, HMatrix< spacedim, Number > &diag_column_block, HMatrix< spacedim, Number > &diag_row_block, const unsigned int fixed_rank, std::mutex &log_stream_lock)
Definition: hmatrix.h:33309
void solve_block_triangular_by_backward_substitution(Vector< Number > &x, const Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_block_diagonal=false) const
Definition: hmatrix.h:32254
void solve_by_forward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_diagonal=true) const
Definition: hmatrix.h:30342
~HMatrix()
Definition: hmatrix.h:19044
void prepare_for_vmult_or_tvmult(const bool is_vmult, const bool is_tvmult)
Definition: hmatrix.h:35129
void set_current_matrix_state(const HMatrixSupport::State state)
Definition: hmatrix.h:19565
HMatrix()
Definition: hmatrix.h:17600
void clear()
Definition: hmatrix.h:18964
void _compute_lu_factorization(HMatrix< spacedim, Number > &LU, const unsigned int fixed_rank) const
Definition: hmatrix.h:32504
void solve_cholesky_transpose_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &X, HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank) const
Definition: hmatrix.h:31253
void Hvmult_task_parallel(const Number2 beta, Vector< Number > &y, const Number3 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:28391
void lu_build_update_to_factorize_dependencies(HMatrix< spacedim, Number > &factorize_block)
Definition: hmatrix.h:33439
void add(HMatrix< spacedim, Number > &C, const Number b, const HMatrix< spacedim, Number > &B, const size_type fixed_rank_k) const
Definition: hmatrix.h:29479
void solve_cholesky_transpose_by_forward_substitution_matrix_valued(HMatrix< spacedim, Number > &Z, const unsigned int fixed_rank) const
Definition: hmatrix.h:31419
void set_block_type(const HMatrixSupport::BlockType block_type)
Definition: hmatrix.h:19673
std::vector< HMatrix< spacedim, Number > * >::iterator find_block_cluster_in_leaf_set(const BlockCluster< spacedim, real_type > &block_cluster)
Definition: hmatrix.h:36027
void clear_hmat_node()
Definition: hmatrix.h:18988
const LAPACKFullMatrixExt< Number > * get_fullmatrix() const
Definition: hmatrix.h:19823
void solve_by_forward_substitution(Vector< Number > &b, const bool is_unit_diagonal=true) const
Definition: hmatrix.h:30244
void set_vmult_strategy(std::unique_ptr< HMatrixVmultStrategy< spacedim, Number > > strategy)
Definition: hmatrix.h:21042
void solve_by_backward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat, const bool is_unit_diagonal=false) const
Definition: hmatrix.h:31930
void get_row_index_range_for_leaf_set_interval(const std::pair< int64_t, int64_t > &interval, const unsigned int thread_no)
Definition: hmatrix.h:34936
bool is_near_field() const
Definition: hmatrix.h:19068
void compute_lu_factorization(HMatrix< spacedim, Number > &LU, const unsigned int fixed_rank)
Definition: hmatrix.h:32473
void Tvmult_add(Vector< Number > &y, const Vector< Number > &x) const
Definition: hmatrix.h:26098
void add(const Number b, const HMatrix< spacedim, Number > &B, const size_type fixed_rank_k) const
Definition: hmatrix.h:29574
void add(HMatrix< spacedim, Number > &C, const Number b, const RkMatrix< Number > &B, const size_type fixed_rank_k)
Definition: hmatrix.h:30213
void _invert_by_gauss_elim(HMatrix< spacedim, Number > &M_inv, const size_type fixed_rank_k)
Definition: hmatrix.h:35424
void invert_by_gauss_elim(HMatrix< spacedim, Number > &M_inv, const size_type fixed_rank_k)
Definition: hmatrix.h:30225
void mmult(HMatrix< spacedim, Number > &C, HMatrix< spacedim, Number > &B, const BlockClusterTree< spacedim, real_type > &bct_a, const BlockClusterTree< spacedim, real_type > &bct_b, BlockClusterTree< spacedim, real_type > &bct_c, const unsigned int fixed_rank=1)
Definition: hmatrix.h:29207
HilbertBlockType
Definition: hmatrix.h:132
double compute_far_field_hmat_assembly_task_cost(const HMatrixSupport::Property top_hmat_property) const
Definition: hmatrix.h:34855
void _print_matrix_info_as_dot_node(std::ostream &out) const
Definition: hmatrix.h:20089
void vmult_serial_iterative(const Number2 beta, Vector< Number > &y, const Number3 alpha, const Vector< Number > &x) const
Definition: hmatrix.h:23104
void cholesky_factorize_diagonal_block_task(tbb::flow::graph &dag, std::mutex &log_stream_lock)
Definition: hmatrix.h:34273
HMatrixSupport::Property property
Definition: hmatrix.h:4263
void Tmmult_level_conserving(HMatrix< spacedim, Number > &C, HMatrix< spacedim, Number > &B, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:29404
HMatrix(typename BlockClusterTree< spacedim, real_type >::node_const_pointer_type bc_node, const LAPACKFullMatrixExt< Number > &M, const HMatrixSupport::Property property=HMatrixSupport::Property::general, const HMatrixSupport::BlockType block_type=HMatrixSupport::BlockType::undefined_block)
Definition: hmatrix.h:17849
void solve_cholesky_by_forward_substitution(Vector< Number > &b, const HMatrix< spacedim, Number > &starting_hmat) const
Definition: hmatrix.h:31809
void get_column(const size_type col_index, Vector< Number > &col_values) const
void fill_col(const size_type col_index, const Vector< Number > &values, const bool is_adding=false)
LAPACKSupport::Property get_property() const
std::make_unsigned< types::blas_int >::type size_type
void set_property(const LAPACKSupport::Property property)
void mTmult(LAPACKFullMatrixExt< Number > &C, const LAPACKFullMatrixExt< Number > &B, bool adding=false) const
void fill_row(const size_type row_index, const Vector< Number > &values, const bool is_adding=false)
void print_formatted_to_mat(std::ostream &out, const std::string &name, const unsigned int precision=8, const bool scientific=true, const unsigned int width=0, const char *zero_string="0", const double denominator=1., const double threshold=0.) const
void get_row(const size_type row_index, Vector< Number > &row_values) const
size_type n
Definition: rkmatrix.h:1150
size_type get_n() const
Definition: rkmatrix.h:2479
void reinit(const size_type m, const size_type n, const size_type fixed_rank_k)
Definition: rkmatrix.h:2445
size_type get_m() const
Definition: rkmatrix.h:2471
size_type formal_rank
Definition: rkmatrix.h:1140
size_type m
Definition: rkmatrix.h:1145
void restrictToFullMatrix(const std::array< types::global_dof_index, 2 > &tau_index_range, const std::array< types::global_dof_index, 2 > &sigma_index_range, LAPACKFullMatrixExt< Number > &matrix) const
Definition: rkmatrix.h:2555
size_type rank
Definition: rkmatrix.h:1134
bool convertToFullMatrix(LAPACKFullMatrixExt< Number > &matrix) const
Definition: rkmatrix.h:2535
T & get_data_reference()
Definition: tree.h:899
Configurations for building the project.
#define ARENA_MAX_CONCURRENCY_IN_LU_AND_CHOL
Definition: config.h:59
void print_wall_time(LogStream &log, const Timer &timer, const std::string &activity_name)
This header file contains a set of self-defined generic functors.
InputIterator find_pointer_data(InputIterator first, InputIterator last, const T *value_pointer)
void RefineHMatrixWrtExtendedBlockClusterTree(HMatrix< spacedim, Number > *starting_hmat, HMatrix< spacedim, Number > *current_hmat)
Definition: hmatrix.h:9483
void h_h_mmult_from_leaf_node(HMatrix< spacedim, Number > &M0, HMatrix< spacedim, Number > &M, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const HMatrixSupport::BlockType block_type_for_local_Z, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:12592
DeclException1(ExcInvalidHMatrixType, HMatrixType,<< "Invalid H-matrix node type: "<< arg1)
void convertHMatBlockToRkMatrix(HMatrix< spacedim, Number > *hmat_block, const unsigned int fixed_rank_k, const HMatrix< spacedim, Number > *hmat_root_block=nullptr, size_t *calling_counter=nullptr, const std::string &output_file_base_name=std::string("hmat-bct"))
Definition: hmatrix.h:10017
void h_h_Tmmult_from_leaf_node(HMatrix< spacedim, Number > &M0, HMatrix< spacedim, Number > &M, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const HMatrixSupport::BlockType block_type_for_local_Z, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:15219
void copy_hmatrix_node(HMatrix< spacedim, Number > &hmat_dst, const HMatrix< spacedim, Number > &hmat_src)
Definition: hmatrix.h:17421
void f_h_Tmmult(const LAPACKFullMatrixExt< Number > &M1, HMatrix< spacedim, Number > &M2, LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:12107
void f_h_mmult_for_h_h_mmult(const HMatrix< spacedim, Number > *M1, HMatrix< spacedim, Number > *M2, HMatrix< spacedim, Number > *M, bool is_M1M2_last_in_M_Sigma_P=true)
Definition: hmatrix.h:12342
void h_rk_Tmmult(HMatrix< spacedim, Number > &M1, const RkMatrix< Number > &M2, RkMatrix< Number > &M)
Definition: hmatrix.h:10751
void h_f_mmult_for_h_h_mmult(HMatrix< spacedim, Number > *M1, const HMatrix< spacedim, Number > *M2, HMatrix< spacedim, Number > *M, bool is_M1M2_last_in_M_Sigma_P=true)
Definition: hmatrix.h:11894
void f_h_mmult(const LAPACKFullMatrixExt< Number > &M1, HMatrix< spacedim, Number > &M2, LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:11964
void h_h_mmult_phase2(HMatrix< spacedim, Number > &M, BlockClusterTree< spacedim, typename numbers::NumberTraits< Number >::real_type > &target_bc_tree, const unsigned int fixed_rank)
Definition: hmatrix.h:12474
void rk_h_mmult_for_h_h_mmult(const HMatrix< spacedim, Number > *M1, HMatrix< spacedim, Number > *M2, HMatrix< spacedim, Number > *M, bool is_M1M2_last_in_M_Sigma_P=true)
Definition: hmatrix.h:11411
void h_h_mTmult_level_conserving(HMatrix< spacedim, Number > &M, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:16558
void h_rk_mTmult(HMatrix< spacedim, Number > &M1, const RkMatrix< Number > &M2, RkMatrix< Number > &M)
Definition: hmatrix.h:10601
void h_h_mTmult_from_leaf_node(HMatrix< spacedim, Number > &M0, HMatrix< spacedim, Number > &M, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const HMatrixSupport::BlockType block_type_for_local_Z, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:13910
void h_h_mmult_from_leaf_node_for_parallel_lu(HMatrix< spacedim, Number > &M0, HMatrix< spacedim, Number > &M, const Number alpha, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const HMatrixSupport::BlockType block_type_for_local_Z, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:13410
void rk_h_mmult(const RkMatrix< Number > &M1, HMatrix< spacedim, Number > &M2, RkMatrix< Number > &M)
Definition: hmatrix.h:10959
void rk_h_Tmmult(const RkMatrix< Number > &M1, HMatrix< spacedim, Number > &M2, RkMatrix< Number > &M)
Definition: hmatrix.h:11273
void InitAndCreateHMatrixChildren(HMatrix< spacedim, Number > *hmat, typename BlockClusterTree< spacedim, typename numbers::NumberTraits< Number >::real_type >::node_const_pointer_type bc_node, const unsigned int fixed_rank_k, const HMatrixSupport::Property top_hmat_node_property=HMatrixSupport::Property::general)
Definition: hmatrix.h:4976
void h_rk_mmult_for_h_h_mmult(HMatrix< spacedim, Number > *M1, const HMatrix< spacedim, Number > *M2, HMatrix< spacedim, Number > *M, bool is_M1M2_last_in_M_Sigma_P=true)
Definition: hmatrix.h:10890
void h_h_mTmult_level_conserving_for_parallel_cholesky(HMatrix< spacedim, Number > &M, const Number alpha, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:16887
void h_f_Tmmult(HMatrix< spacedim, Number > &M1, const LAPACKFullMatrixExt< Number > &M2, LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:11603
void h_f_mTmult(HMatrix< spacedim, Number > &M1, const LAPACKFullMatrixExt< Number > &M2, LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:11532
void h_h_Tmmult_level_conserving(HMatrix< spacedim, Number > &M, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:17073
void InitHMatrixWrtBlockClusterNode(HMatrix< spacedim, Number > &hmat, typename BlockClusterTree< spacedim, typename numbers::NumberTraits< Number >::real_type >::node_const_pointer_type bc_node)
Definition: hmatrix.h:4455
HMatrixType
Definition: hmatrix.h:66
@ RkMatrixType
RkMatrixType.
Definition: hmatrix.h:68
@ FullMatrixType
FullMatrixType.
Definition: hmatrix.h:67
@ HierarchicalMatrixType
HierarchicalType.
Definition: hmatrix.h:69
@ UndefinedMatrixType
UndefinedMatrixType.
Definition: hmatrix.h:70
void h_h_mmult_level_conserving_for_parallel_lu(HMatrix< spacedim, Number > &M, const Number alpha, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:16373
void rk_h_mTmult(const RkMatrix< Number > &M1, HMatrix< spacedim, Number > &M2, RkMatrix< Number > &M)
Definition: hmatrix.h:11119
void h_h_mTmult_from_leaf_node_for_parallel_cholesky(HMatrix< spacedim, Number > &M0, HMatrix< spacedim, Number > &M, const Number alpha, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const HMatrixSupport::BlockType block_type_for_local_Z, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:14735
void f_h_mTmult(const LAPACKFullMatrixExt< Number > &M1, HMatrix< spacedim, Number > &M2, LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:12038
void h_h_mmult_phase1_recursion(HMatrix< spacedim, Number > *M, BlockClusterTree< spacedim, typename numbers::NumberTraits< Number >::real_type > &Tind)
Definition: hmatrix.h:12403
void h_f_mmult(HMatrix< spacedim, Number > &M1, const LAPACKFullMatrixExt< Number > &M2, LAPACKFullMatrixExt< Number > &M)
Definition: hmatrix.h:11460
void copy_hmatrix(HMatrix< spacedim, Number > &hmat_dst, const HMatrix< spacedim, Number > &hmat_src)
Definition: hmatrix.h:17518
void h_h_mmult_level_conserving(HMatrix< spacedim, Number > &M, HMatrix< spacedim, Number > &M1, HMatrix< spacedim, Number > &M2, const unsigned int fixed_rank, const bool is_result_matrix_store_tril_only=false)
Definition: hmatrix.h:16039
void InitAndCreateHMatrixChildrenWithoutAlloc(HMatrix< spacedim, Number > *hmat, typename BlockClusterTree< spacedim, typename numbers::NumberTraits< Number >::real_type >::node_const_pointer_type bc_node)
Definition: hmatrix.h:4621
void h_rk_mmult(HMatrix< spacedim, Number > &M1, const RkMatrix< Number > &M2, RkMatrix< Number > &M)
Definition: hmatrix.h:10444
Adapted from deal.ii/lac/lapack_support.h and define some features for an -matrix.
Strategies for top level H-matrix/vector multiplications, namely, vmult , Tvmult ,...
Definition of ranks for different types of numbers.
Definition of rank-k matrix.
Vector< Number > local_tvmult_result
Definition: hmatrix.h:246
std::array< types::global_dof_index, 2 > vmult_result_index_range
Definition: hmatrix.h:178
std::array< types::global_dof_index, 2 > local_tvmult_result_index_range
Definition: hmatrix.h:230
std::array< types::global_dof_index, 2 > local_vmult_result_index_range
Definition: hmatrix.h:208
std::vector< std::array< types::global_dof_index, 2 > > vmult_result_index_ranges_contributed_from_other_threads
Definition: hmatrix.h:255
Vector< Number > local_vmult_result
Definition: hmatrix.h:238
std::pair< int64_t, int64_t > leaf_set_interval
Definition: hmatrix.h:170
std::vector< std::array< types::global_dof_index, 2 > > tvmult_result_index_ranges_contributed_from_other_threads
Definition: hmatrix.h:264
std::array< types::global_dof_index, 2 > tvmult_result_index_range
Definition: hmatrix.h:186
TreeNodeSplitMode
Definition: tree.h:532